├── .idea
├── .name
├── modules
│ ├── EtherSolve.iml
│ └── Abi
│ │ └── EthereumBytecodeTransformer.Abi.iml
├── vcs.xml
├── jsLibraryMappings.xml
├── webContexts.xml
├── runConfigurations.xml
├── compiler.xml
├── misc.xml
└── jarRepositories.xml
├── WebApp
├── src
│ └── main
│ │ ├── resources
│ │ └── application.yml
│ │ └── java
│ │ ├── processing
│ │ ├── GraphvizException.java
│ │ ├── GraphvizProcessor.java
│ │ ├── AddressProcessor.java
│ │ └── BytecodeProcessor.java
│ │ ├── json_utils
│ │ ├── RenderRequestBody.java
│ │ ├── Response.java
│ │ └── PostRequestBody.java
│ │ └── server
│ │ ├── App.java
│ │ ├── GuiController.java
│ │ ├── RenderController.java
│ │ └── ApiController.java
└── build.gradle
├── Logo
└── Logo.png
├── doc
├── resources
│ ├── x.png
│ └── glass.png
├── jquery
│ ├── images
│ │ ├── 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
│ │ ├── 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
│ ├── jszip-utils
│ │ └── dist
│ │ │ ├── jszip-utils-ie.min.js
│ │ │ ├── jszip-utils.min.js
│ │ │ ├── jszip-utils-ie.js
│ │ │ └── jszip-utils.js
│ ├── jquery-ui.structure.min.css
│ └── jquery-ui.structure.css
├── element-list
├── package-search-index.js
├── overview-summary.html
├── deprecated-list.html
├── gson
│ └── package-tree.html
└── etherscan
│ └── package-tree.html
├── artifact
└── EtherSolve.jar
├── .gitattributes
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── Core
├── src
│ ├── main
│ │ └── java
│ │ │ ├── parseTree
│ │ │ ├── NotSolidityContractException.java
│ │ │ ├── SymbolicExecution
│ │ │ │ ├── StackExceededException.java
│ │ │ │ └── UnknownStackElementException.java
│ │ │ └── cfg
│ │ │ │ ├── BasicBlockType.java
│ │ │ │ ├── Cfg.java
│ │ │ │ └── BasicBlock.java
│ │ │ ├── opcodes
│ │ │ ├── BlockOpcode.java
│ │ │ ├── StackOpcode.java
│ │ │ ├── SystemOpcode.java
│ │ │ ├── ArithmeticOpcode.java
│ │ │ ├── ControlFlowOpcode.java
│ │ │ ├── EnvironmentalOpcode.java
│ │ │ ├── arithmeticOpcodes
│ │ │ │ ├── binaryArithmeticOpcodes
│ │ │ │ │ ├── EQOpcode.java
│ │ │ │ │ ├── GTOpcode.java
│ │ │ │ │ ├── OrOpcode.java
│ │ │ │ │ ├── AddOpcode.java
│ │ │ │ │ ├── AndOpcode.java
│ │ │ │ │ ├── DivOpcode.java
│ │ │ │ │ ├── ExpOpcode.java
│ │ │ │ │ ├── LTOpcode.java
│ │ │ │ │ ├── ModOpcode.java
│ │ │ │ │ ├── MulOpcode.java
│ │ │ │ │ ├── SAROpcode.java
│ │ │ │ │ ├── SGTOpcode.java
│ │ │ │ │ ├── SHLOpcode.java
│ │ │ │ │ ├── SHROpcode.java
│ │ │ │ │ ├── SLTOpcode.java
│ │ │ │ │ ├── SubOpcode.java
│ │ │ │ │ ├── XorOpcode.java
│ │ │ │ │ ├── ByteOpcode.java
│ │ │ │ │ ├── SDivOpcode.java
│ │ │ │ │ ├── SHA3Opcode.java
│ │ │ │ │ ├── SModOpcode.java
│ │ │ │ │ └── SignExtendOpcode.java
│ │ │ │ ├── unaryArithmeticOpcodes
│ │ │ │ │ ├── NotOpcode.java
│ │ │ │ │ └── IsZeroOpcode.java
│ │ │ │ ├── ternaryArithmeticOpcodes
│ │ │ │ │ ├── AddModOpcode.java
│ │ │ │ │ └── MulModOpcode.java
│ │ │ │ ├── BinaryArithmeticOpcode.java
│ │ │ │ ├── UnaryArithmeticOpcode.java
│ │ │ │ └── TernaryArithmeticOpcode.java
│ │ │ ├── stackOpcodes
│ │ │ │ ├── PCOpcode.java
│ │ │ │ ├── GasOpcode.java
│ │ │ │ ├── MLoadOpcode.java
│ │ │ │ ├── MSizeOpcode.java
│ │ │ │ ├── SLoadOpcode.java
│ │ │ │ ├── PopOpcode.java
│ │ │ │ ├── MStoreOpcode.java
│ │ │ │ ├── SStoreOpcode.java
│ │ │ │ ├── MStore8Opcode.java
│ │ │ │ ├── DupOpcode.java
│ │ │ │ ├── SwapOpcode.java
│ │ │ │ └── PushOpcode.java
│ │ │ ├── blockOpcodes
│ │ │ │ ├── ChainIdOpcode.java
│ │ │ │ ├── NumberOpcode.java
│ │ │ │ ├── BlockHashOpcode.java
│ │ │ │ ├── CoinBaseOpcode.java
│ │ │ │ ├── GasLimitOpcode.java
│ │ │ │ ├── TimeStampOpcode.java
│ │ │ │ └── DifficultyOpcode.java
│ │ │ ├── systemOpcodes
│ │ │ │ ├── CallOpcode.java
│ │ │ │ ├── CreateOpcode.java
│ │ │ │ ├── CallCodeOpcode.java
│ │ │ │ ├── StaticCallOpcode.java
│ │ │ │ ├── DelegateCallOpcode.java
│ │ │ │ ├── ReturnOpcode.java
│ │ │ │ ├── RevertOpcode.java
│ │ │ │ └── SelfDestructOpcode.java
│ │ │ ├── environmentalOpcodes
│ │ │ │ ├── CallerOpcode.java
│ │ │ │ ├── OriginOpcode.java
│ │ │ │ ├── AddressOpcode.java
│ │ │ │ ├── BalanceOpcode.java
│ │ │ │ ├── CodeSizeOpcode.java
│ │ │ │ ├── GasPriceOpcode.java
│ │ │ │ ├── CallValueOpcode.java
│ │ │ │ ├── ExtCodeHashOpcode.java
│ │ │ │ ├── ExtCodeSizeOpcode.java
│ │ │ │ ├── SelfBalanceOpcode.java
│ │ │ │ ├── CallDataLoadOpcode.java
│ │ │ │ ├── CallDataSizeOpcode.java
│ │ │ │ ├── ReturnDataSizeOpcode.java
│ │ │ │ ├── CodeCopyOpcode.java
│ │ │ │ ├── CallDataCopyOpcode.java
│ │ │ │ ├── ExtCodeCopyOpcode.java
│ │ │ │ └── ReturnDataCopyOpcode.java
│ │ │ ├── controlFlowOpcodes
│ │ │ │ ├── JumpOpcode.java
│ │ │ │ ├── StopOpcode.java
│ │ │ │ ├── JumpIOpcode.java
│ │ │ │ └── JumpDestOpcode.java
│ │ │ ├── InvalidOpcode.java
│ │ │ ├── LogOpcode.java
│ │ │ ├── Opcode.java
│ │ │ └── OpcodeID.java
│ │ │ ├── SolidityInfo
│ │ │ ├── SolidityVersionUnknownException.java
│ │ │ └── SolidityVersion.java
│ │ │ ├── utils
│ │ │ ├── Message.java
│ │ │ ├── Pair.java
│ │ │ └── Triplet.java
│ │ │ └── Main.java
│ └── test
│ │ └── java
│ │ └── parseTree
│ │ └── SymbolicExecutionStackTest.java
└── build.gradle
├── settings.gradle
├── Abi
├── src
│ └── main
│ │ └── java
│ │ ├── rebuiltabi
│ │ ├── fields
│ │ │ ├── RebuiltSolidityTypeID.java
│ │ │ ├── RebuiltIOElement.java
│ │ │ └── RebuiltSolidityType.java
│ │ ├── RebuiltAbi.java
│ │ └── RebuiltAbiFunction.java
│ │ ├── abi
│ │ ├── fields
│ │ │ ├── StateMutability.java
│ │ │ ├── FunctionType.java
│ │ │ ├── SolidityTypeID.java
│ │ │ ├── IOElement.java
│ │ │ └── SolidityType.java
│ │ ├── Abi.java
│ │ ├── HashDB.java
│ │ └── AbiFunction.java
│ │ ├── etherscan
│ │ ├── gson
│ │ │ └── EtherscanResponse.java
│ │ └── EtherScanDownloader.java
│ │ ├── ir
│ │ └── IRCfg.java
│ │ ├── comparation
│ │ ├── AbiComparison.java
│ │ └── AbiComparator.java
│ │ ├── gson
│ │ └── GsonAbi.java
│ │ └── IRExtractor.java
└── build.gradle
├── SecurityAnalysis
├── src
│ └── main
│ │ └── java
│ │ ├── main
│ │ ├── SecurityVulnerability.java
│ │ ├── SecurityDetection.java
│ │ ├── SnippetsTester.java
│ │ └── SecurityAnalysisReport.java
│ │ └── analysers
│ │ ├── TxOrigin.java
│ │ └── StoreAccessAfterUnsafeCall.java
└── build.gradle
├── UI
├── build.gradle
└── src
│ └── main
│ └── java
│ └── graphviz
│ ├── GVEdge.java
│ ├── GVGraph.java
│ ├── GVBlock.java
│ └── MainGV.java
├── LICENSE
├── gradlew.bat
├── .gitignore
└── README.md
/.idea/.name:
--------------------------------------------------------------------------------
1 | EtherSolve
--------------------------------------------------------------------------------
/WebApp/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8081
--------------------------------------------------------------------------------
/Logo/Logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/Logo/Logo.png
--------------------------------------------------------------------------------
/doc/resources/x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/doc/resources/x.png
--------------------------------------------------------------------------------
/artifact/EtherSolve.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/artifact/EtherSolve.jar
--------------------------------------------------------------------------------
/doc/resources/glass.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/doc/resources/glass.png
--------------------------------------------------------------------------------
/.idea/modules/EtherSolve.iml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | *.html linguist-detectable=false
2 | *.css linguist-detectable=false
3 | *.js linguist-detectable=false
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/WebApp/src/main/java/processing/GraphvizException.java:
--------------------------------------------------------------------------------
1 | package processing;
2 |
3 | public class GraphvizException extends Exception {
4 | }
5 |
--------------------------------------------------------------------------------
/doc/jquery/images/ui-icons_222222_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/doc/jquery/images/ui-icons_222222_256x240.png
--------------------------------------------------------------------------------
/doc/jquery/images/ui-icons_2e83ff_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/doc/jquery/images/ui-icons_2e83ff_256x240.png
--------------------------------------------------------------------------------
/doc/jquery/images/ui-icons_454545_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/doc/jquery/images/ui-icons_454545_256x240.png
--------------------------------------------------------------------------------
/doc/jquery/images/ui-icons_888888_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/doc/jquery/images/ui-icons_888888_256x240.png
--------------------------------------------------------------------------------
/doc/jquery/images/ui-icons_cd0a0a_256x240.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/doc/jquery/images/ui-icons_cd0a0a_256x240.png
--------------------------------------------------------------------------------
/doc/jquery/images/ui-bg_glass_55_fbf9ee_1x400.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/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/HEAD/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/HEAD/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/HEAD/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/HEAD/doc/jquery/images/ui-bg_glass_95_fef1ec_1x400.png
--------------------------------------------------------------------------------
/Core/src/main/java/parseTree/NotSolidityContractException.java:
--------------------------------------------------------------------------------
1 | package parseTree;
2 |
3 | public class NotSolidityContractException extends Exception {
4 | }
5 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'EtherSolve'
2 | include 'Core'
3 | include 'Abi'
4 | include 'WebApp'
5 | include 'UI'
6 | include 'SecurityAnalysis'
7 |
8 |
--------------------------------------------------------------------------------
/doc/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SeUniVr/EtherSolve/HEAD/doc/jquery/images/ui-bg_highlight-soft_75_cccccc_1x100.png
--------------------------------------------------------------------------------
/Abi/src/main/java/rebuiltabi/fields/RebuiltSolidityTypeID.java:
--------------------------------------------------------------------------------
1 | package rebuiltabi.fields;
2 |
3 | public enum RebuiltSolidityTypeID {
4 | SIMPLE,
5 | COMPLEX
6 | }
7 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/SymbolicExecution/UnknownStackElementException.java:
--------------------------------------------------------------------------------
1 | package parseTree.SymbolicExecution;
2 |
3 | public class UnknownStackElementException extends Throwable {
4 | }
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.idea/modules/Abi/EthereumBytecodeTransformer.Abi.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/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/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/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 |
--------------------------------------------------------------------------------
/.idea/webContexts.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/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/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/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/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/overview-summary.html:
--------------------------------------------------------------------------------
1 |
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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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.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){"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
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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 "API Address: " + 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 |
--------------------------------------------------------------------------------
/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 | }
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/.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/
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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
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 |
58 |
59 |
62 |
68 |
69 |
79 |
80 | JavaScript is disabled on your browser.
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
93 |
94 |
95 |
96 |
100 |
101 |
102 |
103 |
104 |
121 |
122 |
125 |
126 |
136 |
137 | JavaScript is disabled on your browser.
138 |
139 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/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 |
58 |
59 |
62 |
68 |
69 |
79 |
80 | JavaScript is disabled on your browser.
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
93 |
94 |
95 |
96 |
103 |
104 |
105 | Class Hierarchy
106 |
107 | java.lang.Object
108 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
136 |
137 |
140 |
141 |
151 |
152 | JavaScript is disabled on your browser.
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/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 |
58 |
59 |
62 |
68 |
69 |
79 |
80 | JavaScript is disabled on your browser.
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
93 |
94 |
95 |
96 |
103 |
104 |
105 | Class Hierarchy
106 |
107 | java.lang.Object
108 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
136 |
137 |
140 |
141 |
151 |
152 | JavaScript is disabled on your browser.
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
--------------------------------------------------------------------------------
/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/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 |
--------------------------------------------------------------------------------