├── .github ├── dependabot.yml └── workflows │ ├── build-on-push.yml │ ├── build-release-on-main-push.yml │ └── dependabot-pr-auto-merge.yml ├── .gitignore ├── LICENSE ├── README.md ├── pom.xml └── src ├── main └── java │ └── net │ └── osslabz │ └── evm │ └── abi │ ├── decoder │ ├── AbiDecoder.java │ └── DecodedFunctionCall.java │ ├── definition │ ├── AbiDefinition.java │ └── SolidityType.java │ └── util │ ├── ByteUtil.java │ ├── FileUtil.java │ └── HashUtil.java └── test ├── java └── net │ └── osslabz │ └── evm │ └── abi │ └── AbiDecoderTest.java └── resources ├── abiFiles ├── SereshForwarder.json ├── TetherToken.json ├── UniswapV2Router02.json ├── UniswapV3Router.json ├── UniswapV3SwapRouter.json ├── UniswapV3SwapRouter02.json ├── ZkSync.json ├── uniswapV3Router-input │ └── input_0xeb154fb38972106bfc0e9bce28130379c44d80be292de775e0f43e2c861e0f48 └── zkSync-input │ └── input_0xe35a7dceb1536dfbd819ab6f756e4dcb19ea09541df54abf0f40064ba1163981 └── logback-test.xml /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "maven" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/workflows/build-on-push.yml: -------------------------------------------------------------------------------- 1 | name: build-on-push 2 | 3 | on: 4 | push: 5 | branches-ignore: 6 | - main 7 | 8 | jobs: 9 | build-on-push: 10 | runs-on: ubuntu-latest 11 | 12 | steps: 13 | - name: checkout 14 | uses: actions/checkout@v4 15 | 16 | - name: setup-jdk 17 | uses: actions/setup-java@v4 18 | with: 19 | java-version: 17 20 | distribution: 'temurin' 21 | cache: maven 22 | 23 | - name: maven-build-verify 24 | run: mvn --batch-mode --update-snapshots verify -------------------------------------------------------------------------------- /.github/workflows/build-release-on-main-push.yml: -------------------------------------------------------------------------------- 1 | name: build-release-on-main-push 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build-release-on-main-push: 10 | if: ${{ !contains(github.event.head_commit.message, '[release]') }} # prevent recursive releases 11 | runs-on: ubuntu-latest 12 | 13 | permissions: 14 | contents: write 15 | packages: write 16 | 17 | steps: 18 | - name: checkout 19 | uses: actions/checkout@v4 20 | with: 21 | ref: main 22 | 23 | - name: setup-jdk 24 | uses: actions/setup-java@v4 25 | with: 26 | java-version: 21 27 | distribution: 'temurin' 28 | cache: maven 29 | server-id: ossrh 30 | server-username: MAVEN_USERNAME 31 | server-password: MAVEN_PASSWORD 32 | gpg-private-key: ${{ secrets.OSSRH_GPG_SECRET_KEY }} 33 | gpg-passphrase: MAVEN_GPG_PASSPHRASE 34 | 35 | - name: maven-build-verify 36 | run: mvn --batch-mode verify 37 | 38 | - name: configure-git-user 39 | uses: qoomon/actions--setup-git@v1 40 | with: 41 | user: bot 42 | 43 | - name: publish-on-maven-central 44 | run: mvn --batch-mode -P osslabz-release clean release:clean release:prepare release:perform 45 | env: 46 | MAVEN_USERNAME: ${{ secrets.OSSRH_USERNAME }} 47 | MAVEN_PASSWORD: ${{ secrets.OSSRH_TOKEN }} 48 | MAVEN_GPG_PASSPHRASE: ${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} 49 | 50 | - name: 'get-latest-tag' 51 | id: 'get-latest-tag' 52 | uses: "WyriHaximus/github-action-get-previous-tag@v1" 53 | 54 | - name: create-release-notes 55 | uses: softprops/action-gh-release@v2 56 | with: 57 | generate_release_notes: true 58 | tag_name: ${{ steps.get-latest-tag.outputs.tag }} 59 | 60 | - name: merge-main-to-dev 61 | run: | 62 | git fetch --unshallow 63 | git checkout dev 64 | git pull 65 | git merge --no-ff main -m "[release] auto-merge released main back to dev" 66 | git push -------------------------------------------------------------------------------- /.github/workflows/dependabot-pr-auto-merge.yml: -------------------------------------------------------------------------------- 1 | name: dependabot-pr-auto-merge 2 | 3 | on: pull_request 4 | 5 | 6 | jobs: 7 | dependabot-pr-auto-merge: 8 | runs-on: ubuntu-latest 9 | 10 | permissions: 11 | contents: write 12 | pull-requests: write 13 | 14 | if: github.actor == 'dependabot[bot]' 15 | steps: 16 | - name: dependabot-pr-fetch-metadata 17 | uses: dependabot/fetch-metadata@v2 18 | 19 | - name: dependabot-pr-approve 20 | run: gh pr review --approve "$PR_URL" 21 | env: 22 | PR_URL: ${{github.event.pull_request.html_url}} 23 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}} 24 | 25 | - name: dependabot-pr-auto-merge 26 | run: gh pr merge --auto --merge "$PR_URL" 27 | env: 28 | PR_URL: ${{github.event.pull_request.html_url}} 29 | GH_TOKEN: ${{secrets.GITHUB_TOKEN}} -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ### Maven template 2 | target/ 3 | pom.xml.tag 4 | pom.xml.releaseBackup 5 | pom.xml.versionsBackup 6 | pom.xml.next 7 | release.properties 8 | dependency-reduced-pom.xml 9 | buildNumber.properties 10 | .mvn/timing.properties 11 | # https://github.com/takari/maven-wrapper#usage-without-binary-jar 12 | .mvn/wrapper/maven-wrapper.jar 13 | 14 | ### JetBrains template 15 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 16 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 17 | 18 | # User-specific stuff 19 | .idea/**/workspace.xml 20 | .idea/**/tasks.xml 21 | .idea/**/usage.statistics.xml 22 | .idea/**/dictionaries 23 | .idea/**/shelf 24 | 25 | # Generated files 26 | .idea/**/contentModel.xml 27 | 28 | # Sensitive or high-churn files 29 | .idea/**/dataSources/ 30 | .idea/**/dataSources.ids 31 | .idea/**/dataSources.local.xml 32 | .idea/**/sqlDataSources.xml 33 | .idea/**/dynamic.xml 34 | .idea/**/uiDesigner.xml 35 | .idea/**/dbnavigator.xml 36 | 37 | # Gradle 38 | .idea/**/gradle.xml 39 | .idea/**/libraries 40 | 41 | # Gradle and Maven with auto-import 42 | # When using Gradle or Maven with auto-import, you should exclude module files, 43 | # since they will be recreated, and may cause churn. Uncomment if using 44 | # auto-import. 45 | # .idea/artifacts 46 | # .idea/compiler.xml 47 | # .idea/jarRepositories.xml 48 | # .idea/modules.xml 49 | # .idea/*.iml 50 | # .idea/modules 51 | # *.iml 52 | # *.ipr 53 | 54 | # CMake 55 | cmake-build-*/ 56 | 57 | # Mongo Explorer plugin 58 | .idea/**/mongoSettings.xml 59 | 60 | # File-based project format 61 | *.iws 62 | 63 | # IntelliJ 64 | out/ 65 | 66 | # mpeltonen/sbt-idea plugin 67 | .idea_modules/ 68 | 69 | # JIRA plugin 70 | atlassian-ide-plugin.xml 71 | 72 | # Cursive Clojure plugin 73 | .idea/replstate.xml 74 | 75 | # Crashlytics plugin (for Android Studio and IntelliJ) 76 | com_crashlytics_export_strings.xml 77 | crashlytics.properties 78 | crashlytics-build.properties 79 | fabric.properties 80 | 81 | # Editor-based Rest Client 82 | .idea/httpRequests 83 | 84 | # Android studio 3.1+ serialized cache file 85 | .idea/caches/build_file_checksums.ser 86 | 87 | ### Eclipse template 88 | .metadata 89 | bin/ 90 | tmp/ 91 | *.tmp 92 | *.bak 93 | *.swp 94 | *~.nib 95 | local.properties 96 | .settings/ 97 | .loadpath 98 | .recommenders 99 | 100 | # External tool builders 101 | .externalToolBuilders/ 102 | 103 | # Locally stored "Eclipse launch configurations" 104 | *.launch 105 | 106 | # PyDev specific (Python IDE for Eclipse) 107 | *.pydevproject 108 | 109 | # CDT-specific (C/C++ Development Tooling) 110 | .cproject 111 | 112 | # CDT- autotools 113 | .autotools 114 | 115 | # Java annotation processor (APT) 116 | .factorypath 117 | 118 | # PDT-specific (PHP Development Tools) 119 | .buildpath 120 | 121 | # sbteclipse plugin 122 | .target 123 | 124 | # Tern plugin 125 | .tern-project 126 | 127 | # TeXlipse plugin 128 | .texlipse 129 | 130 | # STS (Spring Tool Suite) 131 | .springBeans 132 | 133 | # Code Recommenders 134 | .recommenders/ 135 | 136 | # Annotation Processing 137 | .apt_generated/ 138 | .apt_generated_test/ 139 | 140 | # Scala IDE specific (Scala & Java development for Eclipse) 141 | .cache-main 142 | .scala_dependencies 143 | .worksheet 144 | 145 | # Uncomment this line if you wish to ignore the project description file. 146 | # Typically, this file would be tracked if it contains build/dependency configurations: 147 | #.project 148 | 149 | .idea/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | EVM ABI Decoder 2 | =============== 3 | ![GitHub](https://img.shields.io/github/license/osslabz/evm-abi-decoder) 4 | ![GitHub Workflow Status](https://img.shields.io/github/actions/workflow/status/osslabz/evm-abi-decoder/build-on-push.yml?branch=main) 5 | [![Maven Central](https://img.shields.io/maven-central/v/net.osslabz/evm-abi-decoder?label=Maven%20Central)](https://search.maven.org/artifact/net.osslabz/evm-abi-decoder) 6 | 7 | EVM ABI Decoder allows to decode raw input data from a EVM transaction (on Ethereum or a compatible chain like Avalanche, BSC etc.) 8 | into a processable format obtained from the contract's ABi definition (JSON). 9 | 10 | **Acknowledgement**: 11 | This project is based on [Bryce Neals's](https://github.com/prettymuchbryce) project [abidecoder](https://github.com/prettymuchbryce/abidecoder) (Kotlin), which itself is a port 12 | of [ConsenSys](https://github.com/ConsenSys) project [abi-decoder](https://github.com/ConsenSys/abi-decoder) (JavaScript). 13 | 14 | The original project is written in Kotlin, only published on [JitPack](https://jitpack.io/) (but not on [Maven Central](https://search.maven.org/)) and depends on the now 15 | deprecated [ethereumj](https://github.com/ethereum/ethereumj). These were enough reasons for me to rewrite it in Java ;-) 16 | 17 | QuickStart 18 | --------- 19 | 20 | Maven 21 | ------ 22 | 23 | ```xml 24 | 25 | 26 | net.osslabz 27 | evm-abi-decoder 28 | 0.1.0 29 | 30 | ``` 31 | 32 | Usage 33 | ------ 34 | 35 | Loads the UniswapV2Router02 contract and parses a swap transaction: 36 | 37 | ```java 38 | // Abi can be found here: https://etherscan.io/address/0x7a250d5630b4cf539739df2c5dacb4c659f2488d#code 39 | AbiDecoder uniswapv2Abi=new AbiDecoder(this.getClass().getResource("/abiFiles/UniswapV2Router02.json").getFile()); 40 | 41 | // tx: https://etherscan.io/tx/0xde2b61c91842494ac208e25a2a64d99997c382f6aaf0719d6a719b5cff1f8a07 42 | String inputData="0x18cbafe5000000000000000000000000000000000000000000000000000000000098968000000000000000000000000000000000000000000000000000165284993ac4ac00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000d4cf8e47beac55b42ae58991785fa326d9384bd10000000000000000000000000000000000000000000000000000000062e8d8510000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; 43 | 44 | /** 45 | * # Name Type Data 46 | * ---------------------------------------------------------------------- 47 | * 0 amountIn uint256 10000000 48 | * 1 amountOutMin uint256 6283178947560620 49 | * 2 path address[] 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 50 | * 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 51 | * 3 to address 0xD4CF8e47BeAC55b42Ae58991785Fa326d9384Bd1 52 | * 4 deadline uint256 1659426897 53 | */ 54 | 55 | DecodedFunctionCall decodedFunctionCall=uniswapv2Abi.decodeFunctionCall(inputData); 56 | 57 | System.out.println(decodedFunctionCall.getName()); // prints swapExactTokensForETH 58 | 59 | ``` 60 | 61 | Logging 62 | ------ 63 | This project uses slf4j-api but doesn't package an implementation. This is up to the using application. For the 64 | tests logback is backing slf4j as implementation, with a default configuration logging to STOUT. 65 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 4.0.0 5 | 6 | net.osslabz 7 | evm-abi-decoder 8 | 0.1.1-SNAPSHOT 9 | 10 | ${project.groupId}:${project.artifactId} 11 | Allows to decode raw input data from an EVM smart contract call (on Ethereum or a compatible chain like 12 | Avalanche, BSC etc.) into a processable format obtained from the contract's ABi definition (JSON). 13 | 14 | https://github.com/osslabz/evm-abi-decoder 15 | 16 | 17 | UTF-8 18 | 8 19 | 20 | ${osslabz.encoding} 21 | ${osslabz.encoding} 22 | 23 | 2024-11-12T08:22:36Z 24 | 25 | ${osslabz.java.version} 26 | 27 | 1.18.38 28 | 29 | 30 | 31 | 32 | GNU General Public License 3 33 | https://www.gnu.org/licenses/gpl-3.0.html 34 | 35 | 36 | 37 | 38 | 39 | Raphael Vullriede 40 | raphael@osslabz.net 41 | osslabz.net 42 | https://www.osslabz.net 43 | 44 | 45 | 46 | 47 | scm:git:https://github.com/osslabz/evm-abi-decoder.git 48 | scm:git:https://github.com/osslabz/evm-abi-decoder.git 49 | https://github.com/osslabz/evm-abi-decoder 50 | main 51 | 52 | 53 | 54 | 55 | com.fasterxml.jackson.core 56 | jackson-databind 57 | 2.19.0 58 | 59 | 60 | 61 | org.apache.commons 62 | commons-lang3 63 | 3.17.0 64 | 65 | 66 | org.apache.commons 67 | commons-collections4 68 | 4.5.0 69 | 70 | 71 | 72 | org.bouncycastle 73 | bcprov-jdk18on 74 | 1.81 75 | 76 | 77 | 78 | org.projectlombok 79 | lombok 80 | ${lombok.version} 81 | provided 82 | 83 | 84 | 85 | 86 | org.slf4j 87 | slf4j-api 88 | 2.0.16 89 | 90 | 91 | 92 | 93 | org.junit.jupiter 94 | junit-jupiter 95 | 5.13.1 96 | test 97 | 98 | 99 | 100 | ch.qos.logback 101 | logback-classic 102 | 1.5.18 103 | test 104 | 105 | 106 | 107 | 108 | 109 | osslabz-release 110 | 111 | 112 | 113 | org.apache.maven.plugins 114 | maven-release-plugin 115 | 3.1.1 116 | 117 | 118 | nl.basjes.maven.release 119 | conventional-commits-version-policy 120 | 1.0.7 121 | 122 | 123 | 124 | 125 | true 126 | false 127 | osslabz-release 128 | @{project.version} 129 | [release] 130 | @{prefix} set version to @{releaseLabel} 131 | @{prefix} prepare for next development iteration 132 | 133 | 134 | ConventionalCommitsVersionPolicy 135 | 136 | ([0-9]+\.[0-9]+\.[0-9]+)$ 137 | 138 | deploy 139 | 140 | 141 | 142 | org.apache.maven.plugins 143 | maven-javadoc-plugin 144 | 3.11.2 145 | 146 | 147 | attach-javadocs 148 | 149 | jar 150 | 151 | 152 | none 153 | false 154 | 155 | 156 | 157 | 158 | 159 | org.apache.maven.plugins 160 | maven-gpg-plugin 161 | 3.2.7 162 | 163 | 164 | sign-artifacts 165 | verify 166 | 167 | sign 168 | 169 | 170 | 171 | --pinentry-mode 172 | loopback 173 | 174 | 175 | 176 | 177 | 178 | 179 | org.sonatype.plugins 180 | nexus-staging-maven-plugin 181 | 1.7.0 182 | true 183 | 184 | ossrh 185 | https://s01.oss.sonatype.org/ 186 | true 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | org.apache.maven.plugins 198 | maven-compiler-plugin 199 | 3.13.0 200 | 201 | ${maven.compiler.release} 202 | 203 | 204 | org.projectlombok 205 | lombok 206 | ${lombok.version} 207 | 208 | 209 | 210 | 211 | 212 | org.apache.maven.plugins 213 | maven-jar-plugin 214 | 3.4.2 215 | 216 | 217 | org.apache.maven.plugins 218 | maven-source-plugin 219 | 3.3.1 220 | 221 | 222 | attach-sources 223 | 224 | jar-no-fork 225 | 226 | 227 | 228 | 229 | 230 | io.github.git-commit-id 231 | git-commit-id-maven-plugin 232 | 9.0.2 233 | 234 | 235 | git-info 236 | 237 | revision 238 | 239 | initialize 240 | 241 | 242 | 243 | true 244 | 245 | git.branch 246 | ^git.build.(time|version)$ 247 | ^git.commit.id.(abbrev|full)$ 248 | 249 | full 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | ossrh 258 | Maven Central 259 | https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/ 260 | 261 | 262 | -------------------------------------------------------------------------------- /src/main/java/net/osslabz/evm/abi/decoder/AbiDecoder.java: -------------------------------------------------------------------------------- 1 | package net.osslabz.evm.abi.decoder; 2 | 3 | import lombok.Getter; 4 | import net.osslabz.evm.abi.definition.AbiDefinition; 5 | import org.bouncycastle.util.encoders.Hex; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | import java.nio.charset.StandardCharsets; 10 | import java.nio.file.Files; 11 | import java.nio.file.Paths; 12 | import java.util.ArrayList; 13 | import java.util.Collections; 14 | import java.util.HashMap; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | @Getter 19 | public class AbiDecoder { 20 | 21 | protected final AbiDefinition abi; 22 | protected final Map methodSignatures = new HashMap<>(); 23 | 24 | public AbiDecoder(String abiFilePath) throws IOException { 25 | this.abi = AbiDefinition.fromJson(new String(Files.readAllBytes(Paths.get(abiFilePath)), StandardCharsets.UTF_8)); 26 | init(); 27 | } 28 | 29 | public AbiDecoder(InputStream inputStream) { 30 | this.abi = AbiDefinition.fromJson(inputStream); 31 | init(); 32 | } 33 | 34 | private void init() { 35 | for (AbiDefinition.Entry entry : this.abi) { 36 | String hexEncodedMethodSignature = Hex.toHexString(entry.encodeSignature()); 37 | this.methodSignatures.put(hexEncodedMethodSignature, entry); 38 | } 39 | } 40 | 41 | public DecodedFunctionCall decodeFunctionCall(String inputData) { 42 | if (inputData == null || (inputData.startsWith("0x") && inputData.length() < 10) || inputData.length() < 8) { 43 | throw new IllegalArgumentException("Can't decode invalid input '" + inputData + "'."); 44 | } 45 | String inputNoPrefix = cleanup(inputData); 46 | 47 | String methodBytes = inputNoPrefix.substring(0, 8); 48 | 49 | if (!this.methodSignatures.containsKey(methodBytes)) { 50 | //return null; 51 | throw new IllegalStateException("Couldn't find method with signature " + methodBytes); 52 | } 53 | AbiDefinition.Entry abiEntry = this.methodSignatures.get(methodBytes); 54 | 55 | if (!(abiEntry instanceof AbiDefinition.Function)) { 56 | throw new IllegalArgumentException("Input data is not a function call, it's of type '" + abiEntry.type + "'."); 57 | } 58 | 59 | AbiDefinition.Function abiFunction = (AbiDefinition.Function) abiEntry; 60 | 61 | List params = new ArrayList<>(abiFunction.inputs.size()); 62 | List decoded = abiFunction.decode(Hex.decode(inputNoPrefix)); 63 | 64 | for (int i = 0; i < decoded.size(); i++) { 65 | AbiDefinition.Entry.Param paramDefinition = abiFunction.inputs.get(i); 66 | DecodedFunctionCall.Param param = new DecodedFunctionCall.Param(paramDefinition.getName(), paramDefinition.getType().getName(), decoded.get(i)); 67 | params.add(param); 68 | } 69 | return new DecodedFunctionCall(abiFunction.name, params); 70 | } 71 | 72 | public List decodeFunctionsCalls(String inputData) { 73 | 74 | DecodedFunctionCall decodedFunctionCall = this.decodeFunctionCall(inputData); 75 | 76 | List resolvedCalls = Collections.singletonList(decodedFunctionCall); 77 | 78 | if (decodedFunctionCall.getName().equalsIgnoreCase("multicall")) { 79 | 80 | DecodedFunctionCall.Param multiCallPayloadData = decodedFunctionCall.getParam("data"); 81 | 82 | if (multiCallPayloadData == null) { 83 | throw new IllegalStateException("multicall function call doesn't contain expected data input param."); 84 | } 85 | 86 | resolvedCalls = new ArrayList<>(); 87 | Object paramValue = multiCallPayloadData.getValue(); 88 | 89 | if (paramValue instanceof String) { 90 | resolvedCalls.add(this.decodeFunctionCall((String) paramValue)); 91 | } else if (paramValue instanceof byte[]) { 92 | resolvedCalls.add(this.decodeFunctionCall(Hex.toHexString((byte[]) paramValue))); 93 | } else if (paramValue instanceof Object[]) { 94 | for (Object singleCallInputData : (Object[]) paramValue) { 95 | if (singleCallInputData instanceof String) { 96 | DecodedFunctionCall call = this.decodeFunctionCall((String) singleCallInputData); 97 | if (call != null) { 98 | resolvedCalls.add(call); 99 | } 100 | } else if (singleCallInputData instanceof byte[]) { 101 | DecodedFunctionCall call = this.decodeFunctionCall(Hex.toHexString((byte[]) singleCallInputData)); 102 | if (call != null) { 103 | resolvedCalls.add(call); 104 | } 105 | } else { 106 | throw new IllegalStateException("Can't decode param name=" + multiCallPayloadData.getName() + ", type=" + multiCallPayloadData.getType() + ", value=" + multiCallPayloadData.getValue()); 107 | } 108 | } 109 | } else { 110 | throw new IllegalStateException("Can't decode param name=" + multiCallPayloadData.getName() + ", type=" + multiCallPayloadData.getType() + ", value=" + multiCallPayloadData.getValue()); 111 | } 112 | } 113 | return resolvedCalls; 114 | } 115 | 116 | 117 | public DecodedFunctionCall decodeLogEvent(List topics, String data) { 118 | if (topics.isEmpty()) { 119 | throw new IllegalArgumentException("Log.topics is empty"); 120 | } 121 | String funcSignature = cleanup(topics.get(0)); 122 | AbiDefinition.Entry abiEntry = methodSignatures.get(funcSignature); 123 | if (abiEntry == null) { 124 | throw new IllegalStateException("Couldn't find method with signature " + funcSignature); 125 | } else { 126 | if (abiEntry instanceof AbiDefinition.Event) { 127 | AbiDefinition.Event abiEvent = (AbiDefinition.Event) abiEntry; 128 | List decoded = abiEvent.decode(hexBytes(data), topics 129 | .stream() 130 | .map(AbiDecoder::hexBytes) 131 | .toArray(byte[][]::new)); 132 | List params = new ArrayList<>(abiEvent.inputs.size()); 133 | for (int i = 0; i < decoded.size(); i++) { 134 | AbiDefinition.Entry.Param paramDefinition = abiEvent.inputs.get(i); 135 | DecodedFunctionCall.Param param = new DecodedFunctionCall.Param(paramDefinition.getName(), paramDefinition.getType() 136 | .getName(), decoded.get(i)); 137 | params.add(param); 138 | } 139 | return new DecodedFunctionCall(abiEvent.name, params); 140 | } else { 141 | throw new IllegalArgumentException("Input data is not a event, it's of type '" + abiEntry.type + "'."); 142 | } 143 | } 144 | } 145 | 146 | private static String cleanup(String hex) { 147 | return hex.startsWith("0x") ? hex.substring(2) : hex; 148 | } 149 | 150 | private static byte[] hexBytes(String hex) { 151 | return Hex.decode(cleanup(hex)); 152 | } 153 | } -------------------------------------------------------------------------------- /src/main/java/net/osslabz/evm/abi/decoder/DecodedFunctionCall.java: -------------------------------------------------------------------------------- 1 | package net.osslabz.evm.abi.decoder; 2 | 3 | import lombok.Data; 4 | import net.osslabz.evm.abi.util.ByteUtil; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Arrays; 8 | import java.util.Collection; 9 | import java.util.LinkedHashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | 14 | @Data 15 | public class DecodedFunctionCall { 16 | 17 | private String name; 18 | private Map params; 19 | 20 | public DecodedFunctionCall(String name, List params) { 21 | this.name = name; 22 | this.params = new LinkedHashMap<>(); 23 | for (Param param : params) { 24 | this.params.put(param.getName().toLowerCase(), param); 25 | } 26 | } 27 | 28 | public Param getParam(String paramName) { 29 | return this.params.get(paramName.toLowerCase()); 30 | } 31 | 32 | public Map params() { 33 | return this.params; 34 | } 35 | 36 | public Collection getParams() { 37 | return this.params.values(); 38 | } 39 | 40 | public List getParamList() { 41 | return new ArrayList<>(this.getParams()); 42 | } 43 | 44 | public int getSize() { 45 | return this.params.size(); 46 | } 47 | 48 | 49 | @Data 50 | public static class Param { 51 | private String name; 52 | private String type; 53 | private Object value; 54 | 55 | public Param(String name, String type, Object value) { 56 | this.name = name; 57 | this.type = type; 58 | if (value instanceof byte[]) { 59 | this.value = "0x" + ByteUtil.toHexString((byte[]) value); 60 | } else if (value instanceof Object[]) { 61 | Object[] valueAsObjectArray = (Object[]) value; 62 | this.value = new Object[valueAsObjectArray.length]; 63 | for (int i = 0; i < valueAsObjectArray.length; i++) { 64 | Object o = valueAsObjectArray[i]; 65 | ((Object[]) this.value)[i] = o instanceof byte[] ? "0x" + ByteUtil.toHexString((byte[]) o) : o; 66 | } 67 | } else { 68 | this.value = value; 69 | } 70 | } 71 | 72 | public String toString() { 73 | String valueString = this.value == null ? "null" : (this.value.getClass().isArray() ? Arrays.toString((Object[]) this.value) : this.value.toString()); 74 | return this.getClass().getName() + "(name=" + this.name + ", type=" + this.getType() + ", value=" + valueString + ")"; 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /src/main/java/net/osslabz/evm/abi/definition/AbiDefinition.java: -------------------------------------------------------------------------------- 1 | package net.osslabz.evm.abi.definition; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonInclude; 5 | import com.fasterxml.jackson.annotation.JsonProperty; 6 | import com.fasterxml.jackson.core.JsonProcessingException; 7 | import com.fasterxml.jackson.databind.DeserializationFeature; 8 | import com.fasterxml.jackson.databind.ObjectMapper; 9 | import com.fasterxml.jackson.databind.annotation.JsonDeserialize; 10 | import com.fasterxml.jackson.databind.util.StdConverter; 11 | import lombok.Data; 12 | import net.osslabz.evm.abi.util.ByteUtil; 13 | import net.osslabz.evm.abi.util.HashUtil; 14 | import org.apache.commons.collections4.CollectionUtils; 15 | import org.apache.commons.collections4.Predicate; 16 | import org.apache.commons.lang3.StringUtils; 17 | 18 | import java.io.IOException; 19 | import java.io.InputStream; 20 | import java.io.Reader; 21 | import java.util.ArrayList; 22 | import java.util.List; 23 | import java.util.stream.Collectors; 24 | 25 | import static com.fasterxml.jackson.annotation.JsonInclude.Include; 26 | import static java.lang.String.format; 27 | import static net.osslabz.evm.abi.definition.SolidityType.IntType.decodeInt; 28 | import static org.apache.commons.collections4.ListUtils.select; 29 | import static org.apache.commons.lang3.ArrayUtils.subarray; 30 | import static org.apache.commons.lang3.StringUtils.join; 31 | import static org.apache.commons.lang3.StringUtils.stripEnd; 32 | 33 | public class AbiDefinition extends ArrayList { 34 | private final static ObjectMapper DEFAULT_MAPPER = new ObjectMapper() 35 | .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) 36 | .enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL); 37 | 38 | public static class ParamSanitizer extends StdConverter { 39 | public ParamSanitizer() { 40 | } 41 | 42 | @Override 43 | public Entry.Param convert(Entry.Param param) { 44 | if (param.type instanceof SolidityType.TupleType) { 45 | for (Entry.Param c : param.components) { 46 | ((SolidityType.TupleType) param.type).getTypes().add(c.getType()); 47 | } 48 | } else if (param.type instanceof SolidityType.ArrayType) { 49 | SolidityType.ArrayType arrayType = (SolidityType.ArrayType) param.type; 50 | if (arrayType.elementType instanceof SolidityType.TupleType) { 51 | for (AbiDefinition.Entry.Param c : param.components) { 52 | ((SolidityType.TupleType) arrayType.elementType).getTypes().add(c.getType()); 53 | } 54 | } 55 | } 56 | return param; 57 | } 58 | } 59 | 60 | public static AbiDefinition fromJson(String json) { 61 | try { 62 | return DEFAULT_MAPPER.readValue(json, AbiDefinition.class); 63 | } catch (IOException e) { 64 | throw new RuntimeException(e); 65 | } 66 | } 67 | 68 | public static AbiDefinition fromJson(Reader reader) { 69 | try { 70 | return DEFAULT_MAPPER.readValue(reader, AbiDefinition.class); 71 | } catch (IOException e) { 72 | throw new RuntimeException(e); 73 | } 74 | } 75 | 76 | public static AbiDefinition fromJson(InputStream inputStream) { 77 | try { 78 | return DEFAULT_MAPPER.readValue(inputStream, AbiDefinition.class); 79 | } catch (IOException e) { 80 | throw new RuntimeException(e); 81 | } 82 | } 83 | 84 | public String toJson() { 85 | try { 86 | return new ObjectMapper().writeValueAsString(this); 87 | } catch (JsonProcessingException e) { 88 | throw new RuntimeException(e); 89 | } 90 | } 91 | 92 | private T find(Class resultClass, final Entry.Type type, final Predicate searchPredicate) { 93 | return (T) CollectionUtils.find(this, entry -> entry.type == type && searchPredicate.evaluate((T) entry)); 94 | } 95 | 96 | public Function findFunction(Predicate searchPredicate) { 97 | return find(Function.class, Entry.Type.function, searchPredicate); 98 | } 99 | 100 | public Event findEvent(Predicate searchPredicate) { 101 | return find(Event.class, Entry.Type.event, searchPredicate); 102 | } 103 | 104 | public Error findError(Predicate searchError) { 105 | return find(Error.class, Entry.Type.error, searchError); 106 | } 107 | 108 | public Constructor findConstructor() { 109 | return find(Constructor.class, Entry.Type.constructor, object -> true); 110 | } 111 | 112 | @Override 113 | public String toString() { 114 | return toJson(); 115 | } 116 | 117 | 118 | @JsonInclude(Include.NON_NULL) 119 | public static abstract class Entry { 120 | 121 | public final Boolean anonymous; 122 | public final Boolean constant; 123 | public final String name; 124 | public final List inputs; 125 | public final List outputs; 126 | public final Type type; 127 | public final Boolean payable; 128 | 129 | public Entry(Boolean anonymous, Boolean constant, String name, List inputs, List outputs, Type type, Boolean payable) { 130 | this.anonymous = anonymous; 131 | this.constant = constant; 132 | this.name = name; 133 | this.inputs = inputs; 134 | this.outputs = outputs; 135 | this.type = type; 136 | this.payable = payable; 137 | } 138 | 139 | @JsonCreator 140 | public static Entry create(@JsonProperty("anonymous") boolean anonymous, 141 | @JsonProperty("constant") boolean constant, 142 | @JsonProperty("name") String name, 143 | @JsonProperty("inputs") List inputs, 144 | @JsonProperty("outputs") List outputs, 145 | @JsonProperty("type") Type type, 146 | @JsonProperty(value = "payable", required = false, defaultValue = "false") Boolean payable) { 147 | Entry result = null; 148 | switch (type) { 149 | case constructor: 150 | result = new Constructor(inputs, outputs); 151 | break; 152 | case function: 153 | case fallback: 154 | result = new Function(constant, name, inputs, outputs, payable); 155 | break; 156 | case receive: 157 | result = new Function(constant, name, inputs, outputs, payable); 158 | break; 159 | case event: 160 | result = new Event(anonymous, name, inputs, outputs); 161 | break; 162 | case error: 163 | result = new Error(name, inputs); 164 | break; 165 | } 166 | 167 | return result; 168 | } 169 | 170 | public String formatSignature() { 171 | StringBuilder paramsTypes = new StringBuilder(); 172 | if (inputs != null) { 173 | for (Param param : inputs) { 174 | String type = formatParamSignature(param); 175 | paramsTypes.append(type).append(","); 176 | } 177 | } 178 | 179 | return format("%s(%s)", name, stripEnd(paramsTypes.toString(), ",")); 180 | } 181 | 182 | public String formatParamSignature(Param param) { 183 | String type = param.type.getCanonicalName(); 184 | if (param.type instanceof SolidityType.TupleType) { 185 | type = "(" + StringUtils.join(param.getComponents().stream().map(this::formatParamSignature).collect(Collectors.toList()), ",") + ")"; 186 | } else if (param.type instanceof SolidityType.ArrayType && ((SolidityType.ArrayType)param.type).elementType instanceof SolidityType.TupleType) { 187 | type = "(" + StringUtils.join(param.getComponents().stream().map(this::formatParamSignature).collect(Collectors.toList()), ",") + ")[]"; 188 | } 189 | return type; 190 | } 191 | 192 | public byte[] fingerprintSignature() { 193 | return HashUtil.hashAsKeccak(formatSignature().getBytes()); 194 | } 195 | 196 | public byte[] encodeSignature() { 197 | return fingerprintSignature(); 198 | } 199 | 200 | public enum Type { 201 | constructor, 202 | function, 203 | event, 204 | fallback, 205 | receive, 206 | error 207 | } 208 | 209 | @Data 210 | @JsonInclude(Include.NON_NULL) 211 | @JsonDeserialize(converter = ParamSanitizer.class) // invoked after class is fully deserialized 212 | public static class Param { 213 | private Boolean indexed; 214 | private String name; 215 | private SolidityType type; 216 | 217 | private List components; 218 | 219 | public static List decodeList(List params, byte[] encoded) { 220 | List result = new ArrayList<>(params.size()); 221 | 222 | int offset = 0; 223 | for (Param param : params) { 224 | Object decoded = param.type.isDynamicType() 225 | ? param.type.decode(encoded, decodeInt(encoded, offset).intValue()) 226 | : param.type.decode(encoded, offset); 227 | result.add(decoded); 228 | 229 | offset += param.type.getFixedSize(); 230 | } 231 | 232 | return result; 233 | } 234 | 235 | @Override 236 | public String toString() { 237 | return format("%s%s%s", type.getCanonicalName(), (indexed != null && indexed) ? " indexed " : " ", name); 238 | } 239 | } 240 | } 241 | 242 | public static class Constructor extends Entry { 243 | 244 | public Constructor(List inputs, List outputs) { 245 | super(null, null, "", inputs, outputs, Type.constructor, false); 246 | } 247 | 248 | public List decode(byte[] encoded) { 249 | return Param.decodeList(inputs, encoded); 250 | } 251 | 252 | public String formatSignature(String contractName) { 253 | return format("function %s(%s)", contractName, join(inputs, ", ")); 254 | } 255 | } 256 | 257 | public static class Function extends Entry { 258 | 259 | private static final int ENCODED_SIGN_LENGTH = 4; 260 | 261 | public Function(boolean constant, String name, List inputs, List outputs, Boolean payable) { 262 | super(null, constant, name, inputs, outputs, Type.function, payable); 263 | } 264 | 265 | public static byte[] extractSignature(byte[] data) { 266 | return subarray(data, 0, ENCODED_SIGN_LENGTH); 267 | } 268 | 269 | public byte[] encode(Object... args) { 270 | return ByteUtil.merge(encodeSignature(), encodeArguments(args)); 271 | } 272 | 273 | private byte[] encodeArguments(Object... args) { 274 | if (args.length > inputs.size()) 275 | throw new RuntimeException("Too many arguments: " + args.length + " > " + inputs.size()); 276 | 277 | int staticSize = 0; 278 | int dynamicCnt = 0; 279 | // calculating static size and number of dynamic params 280 | for (int i = 0; i < args.length; i++) { 281 | SolidityType type = inputs.get(i).type; 282 | if (type.isDynamicType()) { 283 | dynamicCnt++; 284 | } 285 | staticSize += type.getFixedSize(); 286 | } 287 | 288 | byte[][] bb = new byte[args.length + dynamicCnt][]; 289 | for (int curDynamicPtr = staticSize, curDynamicCnt = 0, i = 0; i < args.length; i++) { 290 | SolidityType type = inputs.get(i).type; 291 | if (type.isDynamicType()) { 292 | byte[] dynBB = type.encode(args[i]); 293 | bb[i] = SolidityType.IntType.encodeInt(curDynamicPtr); 294 | bb[args.length + curDynamicCnt] = dynBB; 295 | curDynamicCnt++; 296 | curDynamicPtr += dynBB.length; 297 | } else { 298 | bb[i] = type.encode(args[i]); 299 | } 300 | } 301 | 302 | return ByteUtil.merge(bb); 303 | } 304 | 305 | public List decode(byte[] encoded) { 306 | return Param.decodeList(inputs, subarray(encoded, ENCODED_SIGN_LENGTH, encoded.length)); 307 | } 308 | 309 | public List decodeResult(byte[] encoded) { 310 | return Param.decodeList(outputs, encoded); 311 | } 312 | 313 | @Override 314 | public byte[] encodeSignature() { 315 | return extractSignature(super.encodeSignature()); 316 | } 317 | 318 | @Override 319 | public String toString() { 320 | String returnTail = ""; 321 | if (constant) { 322 | returnTail += " constant"; 323 | } 324 | if (!outputs.isEmpty()) { 325 | List types = new ArrayList<>(); 326 | for (Param output : outputs) { 327 | types.add(output.type.getCanonicalName()); 328 | } 329 | returnTail += format(" returns(%s)", join(types, ", ")); 330 | } 331 | 332 | return format("function %s(%s)%s;", name, join(inputs, ", "), returnTail); 333 | } 334 | } 335 | 336 | public static class Event extends Entry { 337 | 338 | public Event(boolean anonymous, String name, List inputs, List outputs) { 339 | super(anonymous, null, name, inputs, outputs, Type.event, false); 340 | } 341 | 342 | public List decode(byte[] data, byte[][] topics) { 343 | List result = new ArrayList<>(inputs.size()); 344 | 345 | byte[][] argTopics = anonymous ? topics : subarray(topics, 1, topics.length); 346 | List indexedParams = filteredInputs(true); 347 | List indexed = new ArrayList<>(); 348 | for (int i = 0; i < indexedParams.size(); i++) { 349 | Object decodedTopic; 350 | if (indexedParams.get(i).type.isDynamicType()) { 351 | // If arrays (including string and bytes) are used as indexed arguments, 352 | // the Keccak-256 hash of it is stored as topic instead. 353 | decodedTopic = SolidityType.Bytes32Type.decodeBytes32(argTopics[i], 0); 354 | } else { 355 | decodedTopic = indexedParams.get(i).type.decode(argTopics[i]); 356 | } 357 | indexed.add(decodedTopic); 358 | } 359 | List notIndexed = Param.decodeList(filteredInputs(false), data); 360 | 361 | for (Param input : inputs) { 362 | result.add(input.indexed ? indexed.remove(0) : notIndexed.remove(0)); 363 | } 364 | 365 | return result; 366 | } 367 | 368 | private List filteredInputs(final boolean indexed) { 369 | return select(inputs, param -> param.indexed == indexed); 370 | } 371 | 372 | @Override 373 | public String toString() { 374 | return format("event %s(%s);", name, join(inputs, ", ")); 375 | } 376 | } 377 | 378 | public static class Error extends Entry { 379 | public Error(String name, List inputs) { 380 | super(null, null, name, inputs, null, Type.error, false); 381 | } 382 | 383 | public List decode(byte[] encoded) { 384 | return Param.decodeList(inputs, encoded); 385 | } 386 | 387 | @Override 388 | public String toString() { 389 | return format("error %s(%s);", name, join(inputs, ", ")); 390 | } 391 | } 392 | } -------------------------------------------------------------------------------- /src/main/java/net/osslabz/evm/abi/definition/SolidityType.java: -------------------------------------------------------------------------------- 1 | package net.osslabz.evm.abi.definition; 2 | 3 | import com.fasterxml.jackson.annotation.JsonCreator; 4 | import com.fasterxml.jackson.annotation.JsonValue; 5 | import lombok.Getter; 6 | import net.osslabz.evm.abi.util.ByteUtil; 7 | 8 | import java.lang.reflect.Array; 9 | import java.math.BigInteger; 10 | import java.nio.charset.StandardCharsets; 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | 16 | public abstract class SolidityType { 17 | private final static int Int32Size = 32; 18 | /** 19 | * -- GETTER -- 20 | * The type name as it was specified in the interface description 21 | */ 22 | protected String name; 23 | 24 | public SolidityType(String name) { 25 | this.name = name; 26 | } 27 | 28 | @JsonCreator 29 | public static SolidityType getType(String typeName) { 30 | if (typeName.endsWith("]")) return ArrayType.getType(typeName); 31 | if ("bool".equals(typeName)) return new BoolType(); 32 | if (typeName.startsWith("int")) return new IntType(typeName); 33 | if (typeName.startsWith("uint")) return new UnsignedIntType(typeName); 34 | if ("address".equals(typeName)) return new AddressType(); 35 | if ("string".equals(typeName)) return new StringType(); 36 | if ("bytes".equals(typeName)) return new BytesType(); 37 | if ("function".equals(typeName)) return new FunctionType(); 38 | if ("tuple".equals(typeName)) return new TupleType(); 39 | if (typeName.startsWith("bytes")) return new Bytes32Type(typeName); 40 | throw new RuntimeException("Unknown type: " + typeName); 41 | } 42 | 43 | /** 44 | * The type name as it was specified in the interface description 45 | */ 46 | public String getName() { 47 | return name; 48 | } 49 | 50 | /** 51 | * The canonical type name (used for the method signature creation) 52 | * E.g. 'int' - canonical 'int256' 53 | */ 54 | @JsonValue 55 | public String getCanonicalName() { 56 | return getName(); 57 | } 58 | 59 | /** 60 | * Encodes the value according to specific type rules 61 | * 62 | * @param value 63 | */ 64 | public abstract byte[] encode(Object value); 65 | 66 | public abstract Object decode(byte[] encoded, int offset); 67 | 68 | public Object decode(byte[] encoded) { 69 | return decode(encoded, 0); 70 | } 71 | 72 | /** 73 | * @return fixed size in bytes. For the dynamic types returns IntType.getFixedSize() 74 | * which is effectively the int offset to dynamic data 75 | */ 76 | public int getFixedSize() { 77 | return Int32Size; 78 | } 79 | 80 | public boolean isDynamicType() { 81 | return false; 82 | } 83 | 84 | @Override 85 | public String toString() { 86 | return getName(); 87 | } 88 | 89 | 90 | public static abstract class ArrayType extends SolidityType { 91 | SolidityType elementType; 92 | 93 | public ArrayType(String name) { 94 | super(name); 95 | elementType = SolidityType.getType(name.substring(0, name.lastIndexOf("["))); 96 | } 97 | 98 | public static ArrayType getType(String typeName) { 99 | int idx1 = typeName.lastIndexOf("["); 100 | int idx2 = typeName.lastIndexOf("]"); 101 | if (idx1 + 1 == idx2) { 102 | return new DynamicArrayType(typeName); 103 | } else { 104 | return new StaticArrayType(typeName); 105 | } 106 | } 107 | 108 | @Override 109 | public byte[] encode(Object value) { 110 | if (value.getClass().isArray()) { 111 | List elems = new ArrayList<>(); 112 | for (int i = 0; i < Array.getLength(value); i++) { 113 | elems.add(Array.get(value, i)); 114 | } 115 | return encodeList(elems); 116 | } else if (value instanceof List) { 117 | return encodeList((List) value); 118 | } else { 119 | throw new RuntimeException("List value expected for type " + getName()); 120 | } 121 | } 122 | 123 | protected byte[] encodeTuple(List l) { 124 | byte[][] elems; 125 | if (elementType.isDynamicType()) { 126 | elems = new byte[l.size() * 2][]; 127 | int offset = l.size() * Int32Size; 128 | for (int i = 0; i < l.size(); i++) { 129 | elems[i] = IntType.encodeInt(offset); 130 | byte[] encoded = elementType.encode(l.get(i)); 131 | elems[l.size() + i] = encoded; 132 | offset += Int32Size * ((encoded.length - 1) / Int32Size + 1); 133 | } 134 | } else { 135 | elems = new byte[l.size()][]; 136 | for (int i = 0; i < l.size(); i++) { 137 | elems[i] = elementType.encode(l.get(i)); 138 | } 139 | } 140 | return ByteUtil.merge(elems); 141 | } 142 | 143 | public Object[] decodeTuple(byte[] encoded, int origOffset, int len) { 144 | int offset = origOffset; 145 | Object[] ret = new Object[len]; 146 | 147 | for (int i = 0; i < len; i++) { 148 | if (elementType.isDynamicType()) { 149 | ret[i] = elementType.decode(encoded, origOffset + IntType.decodeInt(encoded, offset).intValue()); 150 | } else { 151 | ret[i] = elementType.decode(encoded, offset); 152 | } 153 | offset += elementType.getFixedSize(); 154 | } 155 | return ret; 156 | } 157 | 158 | 159 | public SolidityType getElementType() { 160 | return elementType; 161 | } 162 | 163 | public abstract byte[] encodeList(List l); 164 | } 165 | 166 | public static class StaticArrayType extends ArrayType { 167 | int size; 168 | 169 | public StaticArrayType(String name) { 170 | super(name); 171 | int idx1 = name.lastIndexOf("["); 172 | int idx2 = name.lastIndexOf("]"); 173 | String dim = name.substring(idx1 + 1, idx2); 174 | size = Integer.parseInt(dim); 175 | } 176 | 177 | @Override 178 | public String getCanonicalName() { 179 | return getElementType().getCanonicalName() + "[" + size + "]"; 180 | } 181 | 182 | @Override 183 | public byte[] encodeList(List l) { 184 | if (l.size() != size) 185 | throw new RuntimeException("List size (" + l.size() + ") != " + size + " for type " + getName()); 186 | return encodeTuple(l); 187 | } 188 | 189 | @Override 190 | public Object[] decode(byte[] encoded, int offset) { 191 | return decodeTuple(encoded, offset, size); 192 | } 193 | 194 | @Override 195 | public int getFixedSize() { 196 | if (isDynamicType()) { 197 | return Int32Size; 198 | } else { 199 | return elementType.getFixedSize() * size; 200 | } 201 | } 202 | 203 | @Override 204 | public boolean isDynamicType() { 205 | return getElementType().isDynamicType() && size > 0; 206 | } 207 | } 208 | 209 | public static class DynamicArrayType extends ArrayType { 210 | public DynamicArrayType(String name) { 211 | super(name); 212 | } 213 | 214 | @Override 215 | public String getCanonicalName() { 216 | return elementType.getCanonicalName() + "[]"; 217 | } 218 | 219 | @Override 220 | public byte[] encodeList(List l) { 221 | return ByteUtil.merge(IntType.encodeInt(l.size()), encodeTuple(l)); 222 | } 223 | 224 | @Override 225 | public Object decode(byte[] encoded, int origOffset) { 226 | int len = IntType.decodeInt(encoded, origOffset).intValue(); 227 | return decodeTuple(encoded, origOffset + Int32Size, len); 228 | } 229 | 230 | @Override 231 | public boolean isDynamicType() { 232 | return true; 233 | } 234 | } 235 | 236 | public static class BytesType extends SolidityType { 237 | protected BytesType(String name) { 238 | super(name); 239 | } 240 | 241 | public BytesType() { 242 | super("bytes"); 243 | } 244 | 245 | @Override 246 | public byte[] encode(Object value) { 247 | byte[] bb; 248 | if (value instanceof byte[]) { 249 | bb = (byte[]) value; 250 | } else if (value instanceof String) { 251 | bb = ((String) value).getBytes(); 252 | } else { 253 | throw new RuntimeException("byte[] or String value is expected for type 'bytes'"); 254 | } 255 | byte[] ret = new byte[((bb.length - 1) / Int32Size + 1) * Int32Size]; // padding 32 bytes 256 | System.arraycopy(bb, 0, ret, 0, bb.length); 257 | 258 | return ByteUtil.merge(IntType.encodeInt(bb.length), ret); 259 | } 260 | 261 | @Override 262 | public Object decode(byte[] encoded, int offset) { 263 | int len = IntType.decodeInt(encoded, offset).intValue(); 264 | if (len == 0) return new byte[0]; 265 | offset += Int32Size; 266 | return Arrays.copyOfRange(encoded, offset, offset + len); 267 | } 268 | 269 | @Override 270 | public boolean isDynamicType() { 271 | return true; 272 | } 273 | } 274 | 275 | public static class StringType extends BytesType { 276 | public StringType() { 277 | super("string"); 278 | } 279 | 280 | @Override 281 | public byte[] encode(Object value) { 282 | if (!(value instanceof String)) throw new RuntimeException("String value expected for type 'string'"); 283 | return super.encode(((String) value).getBytes(StandardCharsets.UTF_8)); 284 | } 285 | 286 | @Override 287 | public Object decode(byte[] encoded, int offset) { 288 | return new String((byte[]) super.decode(encoded, offset), StandardCharsets.UTF_8); 289 | } 290 | } 291 | 292 | public static class Bytes32Type extends SolidityType { 293 | public Bytes32Type(String s) { 294 | super(s); 295 | } 296 | 297 | public static byte[] decodeBytes32(byte[] encoded, int offset) { 298 | return Arrays.copyOfRange(encoded, offset, offset + Int32Size); 299 | } 300 | 301 | @Override 302 | public byte[] encode(Object value) { 303 | if (value instanceof Number) { 304 | BigInteger bigInt = new BigInteger(value.toString()); 305 | return IntType.encodeInt(bigInt); 306 | } else if (value instanceof String) { 307 | byte[] ret = new byte[Int32Size]; 308 | byte[] bytes = ((String) value).getBytes(StandardCharsets.UTF_8); 309 | System.arraycopy(bytes, 0, ret, 0, bytes.length); 310 | return ret; 311 | } else if (value instanceof byte[]) { 312 | byte[] bytes = (byte[]) value; 313 | byte[] ret = new byte[Int32Size]; 314 | System.arraycopy(bytes, 0, ret, Int32Size - bytes.length, bytes.length); 315 | return ret; 316 | } 317 | 318 | throw new RuntimeException("Can't encode java type " + value.getClass() + " to bytes32"); 319 | } 320 | 321 | @Override 322 | public Object decode(byte[] encoded, int offset) { 323 | return decodeBytes32(encoded, offset); 324 | } 325 | } 326 | 327 | public static class AddressType extends IntType { 328 | public AddressType() { 329 | super("address"); 330 | } 331 | 332 | @Override 333 | public byte[] encode(Object value) { 334 | if (value instanceof String && !((String) value).startsWith("0x")) { 335 | // address is supposed to be always in hex 336 | value = "0x" + value; 337 | } 338 | byte[] addr = super.encode(value); 339 | for (int i = 0; i < 12; i++) { 340 | if (addr[i] != 0) { 341 | throw new RuntimeException("Invalid address (should be 20 bytes length): " + ByteUtil.toHexString(addr)); 342 | } 343 | } 344 | return addr; 345 | } 346 | 347 | @Override 348 | public Object decode(byte[] encoded, int offset) { 349 | BigInteger bi = (BigInteger) super.decode(encoded, offset); 350 | return ByteUtil.bigIntegerToBytes(bi, 20); 351 | } 352 | } 353 | 354 | public static abstract class NumericType extends SolidityType { 355 | public NumericType(String name) { 356 | super(name); 357 | } 358 | 359 | BigInteger encodeInternal(Object value) { 360 | BigInteger bigInt; 361 | if (value instanceof String) { 362 | String s = ((String) value).toLowerCase().trim(); 363 | int radix = 10; 364 | if (s.startsWith("0x")) { 365 | s = s.substring(2); 366 | radix = 16; 367 | } else if (s.contains("a") || s.contains("b") || s.contains("c") || 368 | s.contains("d") || s.contains("e") || s.contains("f")) { 369 | radix = 16; 370 | } 371 | bigInt = new BigInteger(s, radix); 372 | } else if (value instanceof BigInteger) { 373 | bigInt = (BigInteger) value; 374 | } else if (value instanceof Number) { 375 | bigInt = new BigInteger(value.toString()); 376 | } else if (value instanceof byte[]) { 377 | bigInt = ByteUtil.bytesToBigInteger((byte[]) value); 378 | } else { 379 | throw new RuntimeException("Invalid value for type '" + this + "': " + value + " (" + value.getClass() + ")"); 380 | } 381 | return bigInt; 382 | } 383 | } 384 | 385 | public static class IntType extends NumericType { 386 | public IntType(String name) { 387 | super(name); 388 | } 389 | 390 | public static BigInteger decodeInt(byte[] encoded, int offset) { 391 | return new BigInteger(Arrays.copyOfRange(encoded, offset, offset + Int32Size)); 392 | } 393 | 394 | public static byte[] encodeInt(int i) { 395 | return encodeInt(new BigInteger("" + i)); 396 | } 397 | 398 | public static byte[] encodeInt(BigInteger bigInt) { 399 | return ByteUtil.bigIntegerToBytesSigned(bigInt, Int32Size); 400 | } 401 | 402 | @Override 403 | public String getCanonicalName() { 404 | if (getName().equals("int")) return "int256"; 405 | return super.getCanonicalName(); 406 | } 407 | 408 | @Override 409 | public Object decode(byte[] encoded, int offset) { 410 | return decodeInt(encoded, offset); 411 | } 412 | 413 | @Override 414 | public byte[] encode(Object value) { 415 | BigInteger bigInt = encodeInternal(value); 416 | return encodeInt(bigInt); 417 | } 418 | } 419 | 420 | public static class UnsignedIntType extends NumericType { 421 | public UnsignedIntType(String name) { 422 | super(name); 423 | } 424 | 425 | public static BigInteger decodeInt(byte[] encoded, int offset) { 426 | return new BigInteger(1, Arrays.copyOfRange(encoded, offset, offset + Int32Size)); 427 | } 428 | 429 | public static byte[] encodeInt(int i) { 430 | return encodeInt(new BigInteger("" + i)); 431 | } 432 | 433 | public static byte[] encodeInt(BigInteger bigInt) { 434 | if (bigInt.signum() == -1) { 435 | throw new RuntimeException("Wrong value for uint type: " + bigInt); 436 | } 437 | return ByteUtil.bigIntegerToBytes(bigInt, Int32Size); 438 | } 439 | 440 | @Override 441 | public String getCanonicalName() { 442 | if (getName().equals("uint")) return "uint256"; 443 | return super.getCanonicalName(); 444 | } 445 | 446 | @Override 447 | public byte[] encode(Object value) { 448 | BigInteger bigInt = encodeInternal(value); 449 | return encodeInt(bigInt); 450 | } 451 | 452 | @Override 453 | public Object decode(byte[] encoded, int offset) { 454 | return decodeInt(encoded, offset); 455 | } 456 | } 457 | 458 | public static class BoolType extends IntType { 459 | public BoolType() { 460 | super("bool"); 461 | } 462 | 463 | @Override 464 | public byte[] encode(Object value) { 465 | if (!(value instanceof Boolean)) throw new RuntimeException("Wrong value for bool type: " + value); 466 | return super.encode(value == Boolean.TRUE ? 1 : 0); 467 | } 468 | 469 | @Override 470 | public Object decode(byte[] encoded, int offset) { 471 | return ((Number) super.decode(encoded, offset)).intValue() != 0; 472 | } 473 | } 474 | 475 | @Getter 476 | public static class TupleType extends SolidityType { 477 | 478 | private final List types = new ArrayList<>(); 479 | 480 | public TupleType() { 481 | super("tuple"); 482 | } 483 | 484 | @Override 485 | public boolean isDynamicType() { 486 | return containsDynamicTypes(); 487 | } 488 | 489 | @Override 490 | public int getFixedSize() { 491 | if (isDynamicType()) { 492 | return super.getFixedSize(); 493 | } else { 494 | return types.stream().mapToInt(SolidityType::getFixedSize).sum(); 495 | } 496 | } 497 | 498 | private boolean containsDynamicTypes(){ 499 | return types.stream().anyMatch(SolidityType::isDynamicType); 500 | } 501 | 502 | @Override 503 | public byte[] encode(Object value) { 504 | return new byte[0]; 505 | } 506 | 507 | @Override 508 | public Object decode(byte[] encoded, int origOffset) { 509 | int offset = origOffset; 510 | Object[] ret = new Object[types.size()]; 511 | 512 | for (int i = 0; i < types.size(); i++) { 513 | SolidityType elementType = types.get(i); 514 | if (elementType.isDynamicType()) { 515 | ret[i] = elementType.decode(encoded, origOffset + IntType.decodeInt(encoded, offset).intValue()); 516 | } else { 517 | ret[i] = elementType.decode(encoded, offset); 518 | } 519 | offset += elementType.getFixedSize(); 520 | } 521 | return ret; 522 | } 523 | } 524 | 525 | public static class FunctionType extends Bytes32Type { 526 | public FunctionType() { 527 | super("function"); 528 | } 529 | 530 | @Override 531 | public byte[] encode(Object value) { 532 | if (!(value instanceof byte[])) throw new RuntimeException("Expected byte[] value for FunctionType"); 533 | if (((byte[]) value).length != 24) throw new RuntimeException("Expected byte[24] for FunctionType"); 534 | return super.encode(ByteUtil.merge((byte[]) value, new byte[8])); 535 | } 536 | } 537 | } -------------------------------------------------------------------------------- /src/main/java/net/osslabz/evm/abi/util/ByteUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) [2016] [ ] 3 | * This file is part of the ethereumJ library. 4 | * 5 | * The ethereumJ library is free software: you can redistribute it and/or modify 6 | * it under the terms of the GNU Lesser General Public License as published by 7 | * the Free Software Foundation, either version 3 of the License, or 8 | * (at your option) any later version. 9 | * 10 | * The ethereumJ library is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU Lesser General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU Lesser General Public License 16 | * along with the ethereumJ library. If not, see . 17 | */ 18 | package net.osslabz.evm.abi.util; 19 | 20 | import org.bouncycastle.util.encoders.Hex; 21 | 22 | import java.math.BigInteger; 23 | import java.util.Arrays; 24 | 25 | public class ByteUtil { 26 | 27 | 28 | /** 29 | * Convert a byte-array into a hex String.
30 | * Works similar to {@link Hex#toHexString} 31 | * but allows for null 32 | * 33 | * @param data - byte-array to convert to a hex-string 34 | * @return hex representation of the data.
35 | * Returns an empty String if the input is null 36 | * @see Hex#toHexString 37 | */ 38 | public static String toHexString(byte[] data) { 39 | return data == null ? "" : Hex.toHexString(data); 40 | } 41 | 42 | public static BigInteger bytesToBigInteger(byte[] bb) { 43 | return (bb == null || bb.length == 0) ? BigInteger.ZERO : new BigInteger(1, bb); 44 | } 45 | 46 | 47 | /** 48 | * Omitting sign indication byte. 49 | *

50 | * Instead of org.spongycastle.util.BigIntegers#asUnsignedByteArray(BigInteger 51 | *
we use this custom method to avoid an empty array in case of BigInteger.ZERO 52 | * 53 | * @param value - any big integer number. A null-value will return null 54 | * @return A byte array without a leading zero byte if present in the signed encoding. 55 | * BigInteger.ZERO will return an array with length 1 and byte-value 0. 56 | */ 57 | public static byte[] bigIntegerToBytes(BigInteger value) { 58 | if (value == null) 59 | return null; 60 | 61 | byte[] data = value.toByteArray(); 62 | 63 | if (data.length != 1 && data[0] == 0) { 64 | byte[] tmp = new byte[data.length - 1]; 65 | System.arraycopy(data, 1, tmp, 0, tmp.length); 66 | data = tmp; 67 | } 68 | return data; 69 | } 70 | 71 | /** 72 | * The regular {@link java.math.BigInteger#toByteArray()} method isn't quite what we often need: 73 | * it appends a leading zero to indicate that the number is positive and may need padding. 74 | * 75 | * @param b the integer to format into a byte array 76 | * @param numBytes the desired size of the resulting byte array 77 | * @return numBytes byte long array. 78 | */ 79 | public static byte[] bigIntegerToBytes(BigInteger b, int numBytes) { 80 | if (b == null) 81 | return null; 82 | byte[] bytes = new byte[numBytes]; 83 | byte[] biBytes = b.toByteArray(); 84 | int start = (biBytes.length == numBytes + 1) ? 1 : 0; 85 | int length = Math.min(biBytes.length, numBytes); 86 | System.arraycopy(biBytes, start, bytes, numBytes - length, length); 87 | return bytes; 88 | } 89 | 90 | 91 | public static byte[] bigIntegerToBytesSigned(BigInteger b, int numBytes) { 92 | if (b == null) 93 | return null; 94 | byte[] bytes = new byte[numBytes]; 95 | Arrays.fill(bytes, b.signum() < 0 ? (byte) 0xFF : 0x00); 96 | byte[] biBytes = b.toByteArray(); 97 | int start = (biBytes.length == numBytes + 1) ? 1 : 0; 98 | int length = Math.min(biBytes.length, numBytes); 99 | System.arraycopy(biBytes, start, bytes, numBytes - length, length); 100 | return bytes; 101 | } 102 | 103 | 104 | /** 105 | * @param arrays - arrays to merge 106 | * @return - merged array 107 | */ 108 | public static byte[] merge(byte[]... arrays) { 109 | int count = 0; 110 | for (byte[] array : arrays) { 111 | count += array.length; 112 | } 113 | 114 | // Create new array and copy all array contents 115 | byte[] mergedArray = new byte[count]; 116 | int start = 0; 117 | for (byte[] array : arrays) { 118 | System.arraycopy(array, 0, mergedArray, start, array.length); 119 | start += array.length; 120 | } 121 | return mergedArray; 122 | } 123 | } -------------------------------------------------------------------------------- /src/main/java/net/osslabz/evm/abi/util/FileUtil.java: -------------------------------------------------------------------------------- 1 | package net.osslabz.evm.abi.util; 2 | 3 | import lombok.experimental.UtilityClass; 4 | 5 | import java.io.IOException; 6 | import java.net.URISyntaxException; 7 | import java.net.URL; 8 | import java.nio.charset.StandardCharsets; 9 | import java.nio.file.Files; 10 | import java.nio.file.Paths; 11 | import java.util.Objects; 12 | 13 | @UtilityClass 14 | public class FileUtil { 15 | 16 | public String readFileIntoString(String path) throws URISyntaxException, IOException { 17 | URL resource = Objects.requireNonNull(FileUtil.class.getClassLoader().getResource(path)); 18 | return new String(Files.readAllBytes(Paths.get(resource.toURI())), StandardCharsets.UTF_8); 19 | } 20 | } -------------------------------------------------------------------------------- /src/main/java/net/osslabz/evm/abi/util/HashUtil.java: -------------------------------------------------------------------------------- 1 | package net.osslabz.evm.abi.util; 2 | 3 | import org.bouncycastle.jcajce.provider.digest.Keccak; 4 | 5 | public class HashUtil { 6 | 7 | public static byte[] hashAsKeccak(byte[] input) { 8 | Keccak.Digest256 digest256 = new Keccak.Digest256(); 9 | byte[] output = digest256.digest(input); 10 | return output; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/net/osslabz/evm/abi/AbiDecoderTest.java: -------------------------------------------------------------------------------- 1 | package net.osslabz.evm.abi; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | import net.osslabz.evm.abi.decoder.AbiDecoder; 5 | import net.osslabz.evm.abi.decoder.DecodedFunctionCall; 6 | import net.osslabz.evm.abi.definition.AbiDefinition; 7 | import net.osslabz.evm.abi.util.FileUtil; 8 | import org.bouncycastle.util.encoders.Hex; 9 | import org.junit.jupiter.api.Assertions; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import java.io.File; 13 | import java.io.IOException; 14 | import java.math.BigInteger; 15 | import java.net.URISyntaxException; 16 | import java.util.Arrays; 17 | import java.util.List; 18 | 19 | @Slf4j 20 | public class AbiDecoderTest { 21 | 22 | @Test 23 | public void testDecodeFunctionCallUniswapV2Router02() throws IOException { 24 | 25 | // Abi can be found here: https://etherscan.io/address/0x7a250d5630b4cf539739df2c5dacb4c659f2488d#code 26 | File abiJson = new File(this.getClass().getResource("/abiFiles/UniswapV2Router02.json").getPath()); 27 | AbiDecoder uniswapv2Abi = new AbiDecoder(abiJson.getAbsolutePath()); 28 | 29 | // tx: https://etherscan.io/tx/0xde2b61c91842494ac208e25a2a64d99997c382f6aaf0719d6a719b5cff1f8a07 30 | String inputData = "0x18cbafe5000000000000000000000000000000000000000000000000000000000098968000000000000000000000000000000000000000000000000000165284993ac4ac00000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000d4cf8e47beac55b42ae58991785fa326d9384bd10000000000000000000000000000000000000000000000000000000062e8d8510000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"; 31 | 32 | /** 33 | * # Name Type Data 34 | * 0 amountIn uint256 10000000 35 | * 1 amountOutMin uint256 6283178947560620 36 | * 2 path address[] 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 37 | * 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 38 | * 3 to address 0xD4CF8e47BeAC55b42Ae58991785Fa326d9384Bd1 39 | * 4 deadline uint256 1659426897 40 | */ 41 | 42 | DecodedFunctionCall decodedFunctionCall = uniswapv2Abi.decodeFunctionCall(inputData); 43 | 44 | Assertions.assertEquals("swapExactTokensForETH", decodedFunctionCall.getName()); 45 | 46 | List paramList = decodedFunctionCall.getParamList(); 47 | 48 | DecodedFunctionCall.Param param0 = paramList.get(0); 49 | Assertions.assertEquals("amountIn", param0.getName()); 50 | Assertions.assertEquals("uint256", param0.getType()); 51 | Assertions.assertEquals(BigInteger.valueOf(10000000), param0.getValue()); 52 | 53 | DecodedFunctionCall.Param param1 = paramList.get(1); 54 | Assertions.assertEquals("amountOutMin", param1.getName()); 55 | Assertions.assertEquals("uint256", param1.getType()); 56 | Assertions.assertEquals(new BigInteger("6283178947560620"), param1.getValue()); 57 | 58 | DecodedFunctionCall.Param param2 = paramList.get(2); 59 | Assertions.assertEquals("path", param2.getName()); 60 | Assertions.assertEquals("address[]", param2.getType()); 61 | Assertions.assertEquals(Arrays.toString(new String[]{"0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2"}), Arrays.toString((Object[]) param2.getValue())); 62 | 63 | DecodedFunctionCall.Param param3 = paramList.get(3); 64 | Assertions.assertEquals("to", param3.getName()); 65 | Assertions.assertEquals("address", param3.getType()); 66 | Assertions.assertEquals("0xd4cf8e47beac55b42ae58991785fa326d9384bd1", param3.getValue()); 67 | 68 | DecodedFunctionCall.Param param4 = paramList.get(4); 69 | Assertions.assertEquals("deadline", param4.getName()); 70 | Assertions.assertEquals("uint256", param4.getType()); 71 | Assertions.assertEquals(BigInteger.valueOf(1659426897), param4.getValue()); 72 | } 73 | 74 | @Test 75 | public void testDecodeFunctionCallWithTuple() throws IOException { 76 | File abiJson = new File(this.getClass().getResource("/abiFiles/UniswapV3SwapRouter02.json").getPath()); 77 | AbiDecoder uniswapv3Abi = new AbiDecoder(abiJson.getAbsolutePath()); 78 | 79 | String inputData = "0x04e45aaf000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000002260fac5e5542a773aa44fbcfedf7c193bc2c59900000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000bebc44782c7db0a1a60cb6fe97d0b483032ff1c70000000000000000000000000000000000000000000000000000000000067932000000000000000000000000000000000000000000000000000000000000002a0000000000000000000000000000000000000000000000000000000000000000"; 80 | 81 | DecodedFunctionCall decodedFunctionCall = uniswapv3Abi.decodeFunctionCall(inputData); 82 | 83 | Assertions.assertEquals("exactInputSingle", decodedFunctionCall.getName()); 84 | 85 | 86 | DecodedFunctionCall.Param param0 = decodedFunctionCall.getParams().stream().findFirst().get(); 87 | Assertions.assertEquals("params", param0.getName()); 88 | Assertions.assertEquals("tuple", param0.getType()); 89 | Object[] v = (Object[]) param0.getValue(); 90 | Assertions.assertEquals("0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", v[0].toString()); 91 | Assertions.assertEquals("0x2260fac5e5542a773aa44fbcfedf7c193bc2c599", v[1].toString()); 92 | Assertions.assertEquals("500", v[2].toString()); 93 | Assertions.assertEquals("424242", v[4].toString()); 94 | Assertions.assertEquals("42", v[5].toString()); 95 | } 96 | 97 | 98 | @Test 99 | public void testDecodeFunctionCallUniswapV3SwapRouter02() throws IOException { 100 | 101 | File abiJson = new File(this.getClass().getResource("/abiFiles/UniswapV3SwapRouter02.json").getPath()); 102 | AbiDecoder uniswapv3SwapRouter02Abi = new AbiDecoder(abiJson.getAbsolutePath()); 103 | 104 | // https://etherscan.io/tx/0x731847de5b19b26039f283826ae5218ac7e070ed1b7fff689c2253a3035d8bd6 105 | String inputData = "0x5ae401dc0000000000000000000000000000000000000000000000000000000062ed6b0d000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e4472b43f3000000000000000000000000000000000000000000000000000008c75ee6fb3900000000000000000000000000000000000000000000000001cb1a1493ed3d4b0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000009bbe10ba8ad02c2a54963b3e2a64f1754c90f411000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404b7c00000000000000000000000000000000000000000000000001cb1a1493ed3d4b000000000000000000000000c0da58d88e967d883ef0540db458381e9f5e9c8000000000000000000000000000000000000000000000000000000000"; 106 | List decodedFunctionCalls = uniswapv3SwapRouter02Abi.decodeFunctionsCalls(inputData); 107 | 108 | 109 | int i = 0; 110 | for (DecodedFunctionCall func : decodedFunctionCalls) { 111 | log.debug("{}: function: {}", i, func.getName()); 112 | int p = 0; 113 | for (DecodedFunctionCall.Param param : func.getParams()) { 114 | log.debug("param {}: name={}, type={}, value={}", p, param.getName(), param.getType(), param.getValue()); 115 | p++; 116 | } 117 | i++; 118 | log.debug("-------------------------"); 119 | } 120 | } 121 | 122 | @Test 123 | public void testDecodeFunctionCallUniswapV3SwapRouter02Swap() throws IOException { 124 | 125 | File abiJson = new File(this.getClass().getResource("/abiFiles/UniswapV3SwapRouter02.json").getPath()); 126 | AbiDecoder uniswapv3SwapRouter02Abi = new AbiDecoder(abiJson.getAbsolutePath()); 127 | 128 | // https://etherscan.io/tx/0xb8ea1e889a4b7bfd1a51359801645518e2f648522c6662c4dd2939a5d9fe6ff4 129 | String inputData = "0x5ae401dc0000000000000000000000000000000000000000000000000000000062fba2e2000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e4472b43f3000000000000000000000000000000000000000003a5efc474214c296d933ea100000000000000000000000000000000000000000000000000d5b866fcc68674000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002000000000000000000000000d041e4427412ede81ccac87f08fa3490af61033d000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004449404b7c00000000000000000000000000000000000000000000000000d5b866fcc68674000000000000000000000000caed7876d89f4f67808e0301a1dfb218d73f569000000000000000000000000000000000000000000000000000000000"; 130 | List decodedFunctionCalls = uniswapv3SwapRouter02Abi.decodeFunctionsCalls(inputData); 131 | 132 | 133 | int i = 0; 134 | for (DecodedFunctionCall func : decodedFunctionCalls) { 135 | log.debug("{}: function: {}", i, func.getName()); 136 | int p = 0; 137 | for (DecodedFunctionCall.Param param : func.getParams()) { 138 | log.debug("param {}: name={}, type={}, value={}", p, param.getName(), param.getType(), param.getValue()); 139 | p++; 140 | } 141 | i++; 142 | log.debug("-------------------------"); 143 | } 144 | } 145 | 146 | @Test 147 | public void testDecodeFunctionCallTupleContainingDynamicTypes() throws IOException { 148 | 149 | // https://api-testnet.bscscan.com/api?module=contract&action=getabi&address=0xb7564227245bb161ebf4d350e1056c26801f1366&format=raw 150 | File abiJson = new File(this.getClass().getResource("/abiFiles/SereshForwarder.json").getPath()); 151 | AbiDecoder sereshForwarderAbi = new AbiDecoder(abiJson.getAbsolutePath()); 152 | 153 | // https://testnet.bscscan.com/tx/0x73b80d49777f0c32d45a0a5a7c3487eb9e8da2c93922540c260cdafc3e81a165 154 | String inputData = "0x005575f20000000000000000000000000000000000000000000000000000000000000080967c9812e5f939318262ccbd023be072015c3ad2f470d47ab5e6b13e1ca810a540274bf9ce7b9da08b0003fc05e67d74e993f3381bf00bcba0fef022bf3b8d6a000000000000000000000000000000000000000000000000000000000000001b000000000000000000000000ddcfc6f09a26413c2b0d6224b29738e74102de04000000000000000000000000cbb869911c0acd242c15a03c42ce3ddcdd82ea1b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000038d7ea4c68000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001e4216f62d8000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000e0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000001a0000000000000000000000000000000000000000000000000000000000000003b6261666b7265696263796c746f36667974667336746f796f6f716f6b6272366e333566673767683236646e6f3464766a716c6d743464687a34716d0000000000000000000000000000000000000000000000000000000000000000000000003b6261666b726569647533356c64727965703433797574337275616a747936743278346b3773787077737365347572616b7676366d723763657a696d0000000000000000000000000000000000000000000000000000000000000000000000003b6261666b7265696567616e657563727a6e646b6676726a64346a63346235356174646b707475326d6d3779327372783235617068626b623666373400000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ddcfc6f09a26413c2b0d6224b29738e74102de0400000000000000000000000000000000000000000000000000000000"; 155 | List decodedFunctionCalls = sereshForwarderAbi.decodeFunctionsCalls(inputData); 156 | 157 | int i = 0; 158 | for (DecodedFunctionCall func : decodedFunctionCalls) { 159 | log.debug("{}: function: {}", i, func.getName()); 160 | int p = 0; 161 | for (DecodedFunctionCall.Param param : func.getParams()) { 162 | log.debug("param {}: name={}, type={}, value={}", p, param.getName(), param.getType(), param.getValue()); 163 | p++; 164 | } 165 | i++; 166 | log.debug("-------------------------"); 167 | } 168 | } 169 | 170 | @Test 171 | public void testTupleArrayParamsSignature() { 172 | String funcName = "commitBlocks"; 173 | AbiDecoder decoder = new AbiDecoder(this.getClass() 174 | .getClassLoader() 175 | .getResourceAsStream("abiFiles/ZkSync.json")); 176 | AbiDefinition.Entry func = decoder.getAbi() 177 | .stream() 178 | .filter(e -> funcName.equals(e.name)) 179 | .findAny() 180 | .orElse(null); 181 | Assertions.assertNotNull(func); 182 | Assertions.assertEquals("commitBlocks((uint32,uint64,bytes32,uint256,bytes32,bytes32),(bytes32,bytes,uint256,(bytes,uint32)[],uint32,uint32)[])", func.formatSignature()); 183 | Assertions.assertEquals("45269298", Hex.toHexString(func.encodeSignature())); 184 | } 185 | 186 | @Test 187 | public void testTupleArrayParamsDecode() throws URISyntaxException, IOException { 188 | String funcName = "commitBlocks"; 189 | AbiDecoder decoder = new AbiDecoder(this.getClass() 190 | .getClassLoader() 191 | .getResourceAsStream("abiFiles/ZkSync.json")); 192 | DecodedFunctionCall decode = decoder.decodeFunctionCall(FileUtil.readFileIntoString("abiFiles/zkSync-input/input_0xe35a7dceb1536dfbd819ab6f756e4dcb19ea09541df54abf0f40064ba1163981")); 193 | Assertions.assertNotNull(decode); 194 | Assertions.assertEquals(funcName, decode.getName()); 195 | Assertions.assertEquals(2, decode.getParams().size()); 196 | for (DecodedFunctionCall.Param param : decode.getParams()) { 197 | if ("_lastCommittedBlockData".equals(param.getName())) { 198 | Object[] value = Assertions.assertInstanceOf(Object[].class, param.getValue()); 199 | Assertions.assertEquals(6, value.length); 200 | Assertions.assertArrayEquals(new Object[]{ 201 | new BigInteger("432775"), 202 | new BigInteger("0"), 203 | "0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470", 204 | new BigInteger("1710501302"), 205 | "0x071035b8b917294d5b81ae4c5124ecc2e4d5782c50cb9cfc7d037f7f8af7d791", 206 | "0x316e6378abf242e3494c50d6afc3e929d9be0ad9cfdc5ebaa34ae7b8456dd3f6" 207 | }, value); 208 | } else if ("_newBlocksData".equals(param.getName())) { 209 | Object[] value = Assertions.assertInstanceOf(Object[].class, param.getValue()); 210 | Assertions.assertEquals(10, value.length); 211 | } 212 | } 213 | } 214 | 215 | @Test 216 | public void testTupleParamsSignature() { 217 | String funcName = "exactInput"; 218 | AbiDecoder decoder = new AbiDecoder(this.getClass() 219 | .getClassLoader() 220 | .getResourceAsStream("abiFiles/UniswapV3Router.json")); 221 | AbiDefinition.Entry func = decoder.getAbi() 222 | .stream() 223 | .filter(e -> funcName.equals(e.name)) 224 | .findAny() 225 | .orElse(null); 226 | Assertions.assertNotNull(func); 227 | Assertions.assertEquals("exactInput((bytes,address,uint256,uint256,uint256))", func.formatSignature()); 228 | Assertions.assertEquals("c04b8d59", Hex.toHexString(func.encodeSignature())); 229 | } 230 | 231 | @Test 232 | public void testUniswapV3Router() throws URISyntaxException, IOException { 233 | String funcName = "exactInput"; 234 | AbiDecoder decoder = new AbiDecoder(this.getClass() 235 | .getClassLoader() 236 | .getResourceAsStream("abiFiles/UniswapV3Router.json")); 237 | DecodedFunctionCall decode = decoder.decodeFunctionCall(FileUtil.readFileIntoString("abiFiles/uniswapV3Router-input/input_0xeb154fb38972106bfc0e9bce28130379c44d80be292de775e0f43e2c861e0f48")); 238 | Assertions.assertNotNull(decode); 239 | Assertions.assertEquals(funcName, decode.getName()); 240 | Assertions.assertEquals(1, decode.getParams().size()); 241 | DecodedFunctionCall.Param param = decode.getParams().stream().findFirst().orElse(null); 242 | Assertions.assertNotNull(param); 243 | Object[] value = Assertions.assertInstanceOf(Object[].class, param.getValue()); 244 | Assertions.assertEquals(5, value.length); 245 | Assertions.assertArrayEquals(new Object[]{ 246 | "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb8514910771af9ca656af840dff83e8264ecf986ca000bb8dac17f958d2ee523a2206206994597c13d831ec7", 247 | "0x9e3df1cd92386519734558178e535e0460b10ab6", 248 | new BigInteger("1692606069"), 249 | new BigInteger("500000000000000"), 250 | new BigInteger("843698") 251 | }, value); 252 | } 253 | 254 | @Test 255 | public void testUSDTTransferLog() { 256 | AbiDecoder decoder = new AbiDecoder(this.getClass() 257 | .getClassLoader() 258 | .getResourceAsStream("abiFiles/TetherToken.json")); 259 | DecodedFunctionCall log = decoder.decodeLogEvent(Arrays.asList( 260 | "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", 261 | "0x000000000000000000000000abea9132b05a70803a4e85094fd0e1800777fbef", 262 | "0x00000000000000000000000047c27dea4d3625169a3dcad8c1fc4375e1c0a8fc"), 263 | "0x000000000000000000000000000000000000000000000000000000000edc4c64"); 264 | Assertions.assertEquals("Transfer", log.getName()); 265 | Assertions.assertEquals(3, log.getParams().size()); 266 | Assertions.assertEquals("0xabea9132b05a70803a4e85094fd0e1800777fbef", log.params().get("from").getValue()); 267 | Assertions.assertEquals("0x47c27dea4d3625169a3dcad8c1fc4375e1c0a8fc", log.params().get("to").getValue()); 268 | Assertions.assertEquals(BigInteger.valueOf(249318500), log.params().get("value").getValue()); 269 | } 270 | 271 | @Test 272 | public void testLogWrongInput() { 273 | AbiDecoder decoder = new AbiDecoder(this.getClass() 274 | .getClassLoader() 275 | .getResourceAsStream("abiFiles/TetherToken.json")); 276 | Assertions.assertThrows(IllegalStateException.class, () -> decoder.decodeLogEvent(Arrays.asList("0xefef619ae4a542a2b8810b4efeccd8478bd683e985354ee31dd2d644aff6d0ca", 277 | "0x000000000000000000000000a5ece9bab9a0e56ad63ad0734033c944eeb00e1a", 278 | "0x0000000000000000000000000000000000000000000000000000000000000000"), 279 | "0x0000000000000000000000000000000000000000000000000020affce72f5800")); 280 | } 281 | } -------------------------------------------------------------------------------- /src/test/resources/abiFiles/SereshForwarder.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "uint256", 6 | "name": "_chainId", 7 | "type": "uint256" 8 | } 9 | ], 10 | "stateMutability": "nonpayable", 11 | "type": "constructor" 12 | }, { 13 | "inputs": [], 14 | "name": "InvalidShortString", 15 | "type": "error" 16 | }, { 17 | "inputs": [ 18 | { 19 | "internalType": "string", 20 | "name": "str", 21 | "type": "string" 22 | } 23 | ], 24 | "name": "StringTooLong", 25 | "type": "error" 26 | }, { 27 | "anonymous": false, 28 | "inputs": [], 29 | "name": "EIP712DomainChanged", 30 | "type": "event" 31 | }, { 32 | "anonymous": false, 33 | "inputs": [ 34 | { 35 | "indexed": true, 36 | "internalType": "address", 37 | "name": "previousOwner", 38 | "type": "address" 39 | }, { 40 | "indexed": true, 41 | "internalType": "address", 42 | "name": "newOwner", 43 | "type": "address" 44 | } 45 | ], 46 | "name": "OwnershipTransferred", 47 | "type": "event" 48 | }, { 49 | "inputs": [], 50 | "name": "chainId", 51 | "outputs": [ 52 | { 53 | "internalType": "uint256", 54 | "name": "", 55 | "type": "uint256" 56 | } 57 | ], 58 | "stateMutability": "view", 59 | "type": "function" 60 | }, { 61 | "inputs": [], 62 | "name": "eip712Domain", 63 | "outputs": [ 64 | { 65 | "internalType": "bytes1", 66 | "name": "fields", 67 | "type": "bytes1" 68 | }, { 69 | "internalType": "string", 70 | "name": "name", 71 | "type": "string" 72 | }, { 73 | "internalType": "string", 74 | "name": "version", 75 | "type": "string" 76 | }, { 77 | "internalType": "uint256", 78 | "name": "chainId", 79 | "type": "uint256" 80 | }, { 81 | "internalType": "address", 82 | "name": "verifyingContract", 83 | "type": "address" 84 | }, { 85 | "internalType": "bytes32", 86 | "name": "salt", 87 | "type": "bytes32" 88 | }, { 89 | "internalType": "uint256[]", 90 | "name": "extensions", 91 | "type": "uint256[]" 92 | } 93 | ], 94 | "stateMutability": "view", 95 | "type": "function" 96 | }, { 97 | "inputs": [ 98 | { 99 | "components": [ 100 | { 101 | "internalType": "address", 102 | "name": "from", 103 | "type": "address" 104 | }, { 105 | "internalType": "address", 106 | "name": "to", 107 | "type": "address" 108 | }, { 109 | "internalType": "uint256", 110 | "name": "value", 111 | "type": "uint256" 112 | }, { 113 | "internalType": "uint256", 114 | "name": "gas", 115 | "type": "uint256" 116 | }, { 117 | "internalType": "uint256", 118 | "name": "nonce", 119 | "type": "uint256" 120 | }, { 121 | "internalType": "bytes", 122 | "name": "data", 123 | "type": "bytes" 124 | } 125 | ], 126 | "internalType": "struct SereshForwarder.ForwardRequest", 127 | "name": "req", 128 | "type": "tuple" 129 | }, { 130 | "internalType": "bytes32", 131 | "name": "sigR", 132 | "type": "bytes32" 133 | }, { 134 | "internalType": "bytes32", 135 | "name": "sigS", 136 | "type": "bytes32" 137 | }, { 138 | "internalType": "uint8", 139 | "name": "sigV", 140 | "type": "uint8" 141 | } 142 | ], 143 | "name": "execute", 144 | "outputs": [ 145 | { 146 | "internalType": "bool", 147 | "name": "", 148 | "type": "bool" 149 | }, { 150 | "internalType": "bytes", 151 | "name": "", 152 | "type": "bytes" 153 | } 154 | ], 155 | "stateMutability": "payable", 156 | "type": "function" 157 | }, { 158 | "inputs": [ 159 | { 160 | "internalType": "address", 161 | "name": "from", 162 | "type": "address" 163 | } 164 | ], 165 | "name": "getNonce", 166 | "outputs": [ 167 | { 168 | "internalType": "uint256", 169 | "name": "", 170 | "type": "uint256" 171 | } 172 | ], 173 | "stateMutability": "view", 174 | "type": "function" 175 | }, { 176 | "inputs": [], 177 | "name": "owner", 178 | "outputs": [ 179 | { 180 | "internalType": "address", 181 | "name": "", 182 | "type": "address" 183 | } 184 | ], 185 | "stateMutability": "view", 186 | "type": "function" 187 | }, { 188 | "inputs": [], 189 | "name": "renounceOwnership", 190 | "outputs": [], 191 | "stateMutability": "nonpayable", 192 | "type": "function" 193 | }, { 194 | "inputs": [ 195 | { 196 | "internalType": "address", 197 | "name": "newOwner", 198 | "type": "address" 199 | } 200 | ], 201 | "name": "transferOwnership", 202 | "outputs": [], 203 | "stateMutability": "nonpayable", 204 | "type": "function" 205 | }, { 206 | "inputs": [ 207 | { 208 | "components": [ 209 | { 210 | "internalType": "address", 211 | "name": "from", 212 | "type": "address" 213 | }, { 214 | "internalType": "address", 215 | "name": "to", 216 | "type": "address" 217 | }, { 218 | "internalType": "uint256", 219 | "name": "value", 220 | "type": "uint256" 221 | }, { 222 | "internalType": "uint256", 223 | "name": "gas", 224 | "type": "uint256" 225 | }, { 226 | "internalType": "uint256", 227 | "name": "nonce", 228 | "type": "uint256" 229 | }, { 230 | "internalType": "bytes", 231 | "name": "data", 232 | "type": "bytes" 233 | } 234 | ], 235 | "internalType": "struct SereshForwarder.ForwardRequest", 236 | "name": "req", 237 | "type": "tuple" 238 | }, { 239 | "internalType": "bytes32", 240 | "name": "sigR", 241 | "type": "bytes32" 242 | }, { 243 | "internalType": "bytes32", 244 | "name": "sigS", 245 | "type": "bytes32" 246 | }, { 247 | "internalType": "uint8", 248 | "name": "sigV", 249 | "type": "uint8" 250 | } 251 | ], 252 | "name": "verify", 253 | "outputs": [ 254 | { 255 | "internalType": "bool", 256 | "name": "", 257 | "type": "bool" 258 | } 259 | ], 260 | "stateMutability": "view", 261 | "type": "function" 262 | } 263 | ] 264 | -------------------------------------------------------------------------------- /src/test/resources/abiFiles/TetherToken.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "constant":true, 4 | "inputs":[ 5 | 6 | ], 7 | "name":"name", 8 | "outputs":[ 9 | { 10 | "name":"", 11 | "type":"string" 12 | } 13 | ], 14 | "payable":false, 15 | "stateMutability":"view", 16 | "type":"function" 17 | }, 18 | { 19 | "constant":false, 20 | "inputs":[ 21 | { 22 | "name":"_upgradedAddress", 23 | "type":"address" 24 | } 25 | ], 26 | "name":"deprecate", 27 | "outputs":[ 28 | 29 | ], 30 | "payable":false, 31 | "stateMutability":"nonpayable", 32 | "type":"function" 33 | }, 34 | { 35 | "constant":false, 36 | "inputs":[ 37 | { 38 | "name":"_spender", 39 | "type":"address" 40 | }, 41 | { 42 | "name":"_value", 43 | "type":"uint256" 44 | } 45 | ], 46 | "name":"approve", 47 | "outputs":[ 48 | 49 | ], 50 | "payable":false, 51 | "stateMutability":"nonpayable", 52 | "type":"function" 53 | }, 54 | { 55 | "constant":true, 56 | "inputs":[ 57 | 58 | ], 59 | "name":"deprecated", 60 | "outputs":[ 61 | { 62 | "name":"", 63 | "type":"bool" 64 | } 65 | ], 66 | "payable":false, 67 | "stateMutability":"view", 68 | "type":"function" 69 | }, 70 | { 71 | "constant":false, 72 | "inputs":[ 73 | { 74 | "name":"_evilUser", 75 | "type":"address" 76 | } 77 | ], 78 | "name":"addBlackList", 79 | "outputs":[ 80 | 81 | ], 82 | "payable":false, 83 | "stateMutability":"nonpayable", 84 | "type":"function" 85 | }, 86 | { 87 | "constant":true, 88 | "inputs":[ 89 | 90 | ], 91 | "name":"totalSupply", 92 | "outputs":[ 93 | { 94 | "name":"", 95 | "type":"uint256" 96 | } 97 | ], 98 | "payable":false, 99 | "stateMutability":"view", 100 | "type":"function" 101 | }, 102 | { 103 | "constant":false, 104 | "inputs":[ 105 | { 106 | "name":"_from", 107 | "type":"address" 108 | }, 109 | { 110 | "name":"_to", 111 | "type":"address" 112 | }, 113 | { 114 | "name":"_value", 115 | "type":"uint256" 116 | } 117 | ], 118 | "name":"transferFrom", 119 | "outputs":[ 120 | 121 | ], 122 | "payable":false, 123 | "stateMutability":"nonpayable", 124 | "type":"function" 125 | }, 126 | { 127 | "constant":true, 128 | "inputs":[ 129 | 130 | ], 131 | "name":"upgradedAddress", 132 | "outputs":[ 133 | { 134 | "name":"", 135 | "type":"address" 136 | } 137 | ], 138 | "payable":false, 139 | "stateMutability":"view", 140 | "type":"function" 141 | }, 142 | { 143 | "constant":true, 144 | "inputs":[ 145 | { 146 | "name":"", 147 | "type":"address" 148 | } 149 | ], 150 | "name":"balances", 151 | "outputs":[ 152 | { 153 | "name":"", 154 | "type":"uint256" 155 | } 156 | ], 157 | "payable":false, 158 | "stateMutability":"view", 159 | "type":"function" 160 | }, 161 | { 162 | "constant":true, 163 | "inputs":[ 164 | 165 | ], 166 | "name":"decimals", 167 | "outputs":[ 168 | { 169 | "name":"", 170 | "type":"uint256" 171 | } 172 | ], 173 | "payable":false, 174 | "stateMutability":"view", 175 | "type":"function" 176 | }, 177 | { 178 | "constant":true, 179 | "inputs":[ 180 | 181 | ], 182 | "name":"maximumFee", 183 | "outputs":[ 184 | { 185 | "name":"", 186 | "type":"uint256" 187 | } 188 | ], 189 | "payable":false, 190 | "stateMutability":"view", 191 | "type":"function" 192 | }, 193 | { 194 | "constant":true, 195 | "inputs":[ 196 | 197 | ], 198 | "name":"_totalSupply", 199 | "outputs":[ 200 | { 201 | "name":"", 202 | "type":"uint256" 203 | } 204 | ], 205 | "payable":false, 206 | "stateMutability":"view", 207 | "type":"function" 208 | }, 209 | { 210 | "constant":false, 211 | "inputs":[ 212 | 213 | ], 214 | "name":"unpause", 215 | "outputs":[ 216 | 217 | ], 218 | "payable":false, 219 | "stateMutability":"nonpayable", 220 | "type":"function" 221 | }, 222 | { 223 | "constant":true, 224 | "inputs":[ 225 | { 226 | "name":"_maker", 227 | "type":"address" 228 | } 229 | ], 230 | "name":"getBlackListStatus", 231 | "outputs":[ 232 | { 233 | "name":"", 234 | "type":"bool" 235 | } 236 | ], 237 | "payable":false, 238 | "stateMutability":"view", 239 | "type":"function" 240 | }, 241 | { 242 | "constant":true, 243 | "inputs":[ 244 | { 245 | "name":"", 246 | "type":"address" 247 | }, 248 | { 249 | "name":"", 250 | "type":"address" 251 | } 252 | ], 253 | "name":"allowed", 254 | "outputs":[ 255 | { 256 | "name":"", 257 | "type":"uint256" 258 | } 259 | ], 260 | "payable":false, 261 | "stateMutability":"view", 262 | "type":"function" 263 | }, 264 | { 265 | "constant":true, 266 | "inputs":[ 267 | 268 | ], 269 | "name":"paused", 270 | "outputs":[ 271 | { 272 | "name":"", 273 | "type":"bool" 274 | } 275 | ], 276 | "payable":false, 277 | "stateMutability":"view", 278 | "type":"function" 279 | }, 280 | { 281 | "constant":true, 282 | "inputs":[ 283 | { 284 | "name":"who", 285 | "type":"address" 286 | } 287 | ], 288 | "name":"balanceOf", 289 | "outputs":[ 290 | { 291 | "name":"", 292 | "type":"uint256" 293 | } 294 | ], 295 | "payable":false, 296 | "stateMutability":"view", 297 | "type":"function" 298 | }, 299 | { 300 | "constant":false, 301 | "inputs":[ 302 | 303 | ], 304 | "name":"pause", 305 | "outputs":[ 306 | 307 | ], 308 | "payable":false, 309 | "stateMutability":"nonpayable", 310 | "type":"function" 311 | }, 312 | { 313 | "constant":true, 314 | "inputs":[ 315 | 316 | ], 317 | "name":"getOwner", 318 | "outputs":[ 319 | { 320 | "name":"", 321 | "type":"address" 322 | } 323 | ], 324 | "payable":false, 325 | "stateMutability":"view", 326 | "type":"function" 327 | }, 328 | { 329 | "constant":true, 330 | "inputs":[ 331 | 332 | ], 333 | "name":"owner", 334 | "outputs":[ 335 | { 336 | "name":"", 337 | "type":"address" 338 | } 339 | ], 340 | "payable":false, 341 | "stateMutability":"view", 342 | "type":"function" 343 | }, 344 | { 345 | "constant":true, 346 | "inputs":[ 347 | 348 | ], 349 | "name":"symbol", 350 | "outputs":[ 351 | { 352 | "name":"", 353 | "type":"string" 354 | } 355 | ], 356 | "payable":false, 357 | "stateMutability":"view", 358 | "type":"function" 359 | }, 360 | { 361 | "constant":false, 362 | "inputs":[ 363 | { 364 | "name":"_to", 365 | "type":"address" 366 | }, 367 | { 368 | "name":"_value", 369 | "type":"uint256" 370 | } 371 | ], 372 | "name":"transfer", 373 | "outputs":[ 374 | 375 | ], 376 | "payable":false, 377 | "stateMutability":"nonpayable", 378 | "type":"function" 379 | }, 380 | { 381 | "constant":false, 382 | "inputs":[ 383 | { 384 | "name":"newBasisPoints", 385 | "type":"uint256" 386 | }, 387 | { 388 | "name":"newMaxFee", 389 | "type":"uint256" 390 | } 391 | ], 392 | "name":"setParams", 393 | "outputs":[ 394 | 395 | ], 396 | "payable":false, 397 | "stateMutability":"nonpayable", 398 | "type":"function" 399 | }, 400 | { 401 | "constant":false, 402 | "inputs":[ 403 | { 404 | "name":"amount", 405 | "type":"uint256" 406 | } 407 | ], 408 | "name":"issue", 409 | "outputs":[ 410 | 411 | ], 412 | "payable":false, 413 | "stateMutability":"nonpayable", 414 | "type":"function" 415 | }, 416 | { 417 | "constant":false, 418 | "inputs":[ 419 | { 420 | "name":"amount", 421 | "type":"uint256" 422 | } 423 | ], 424 | "name":"redeem", 425 | "outputs":[ 426 | 427 | ], 428 | "payable":false, 429 | "stateMutability":"nonpayable", 430 | "type":"function" 431 | }, 432 | { 433 | "constant":true, 434 | "inputs":[ 435 | { 436 | "name":"_owner", 437 | "type":"address" 438 | }, 439 | { 440 | "name":"_spender", 441 | "type":"address" 442 | } 443 | ], 444 | "name":"allowance", 445 | "outputs":[ 446 | { 447 | "name":"remaining", 448 | "type":"uint256" 449 | } 450 | ], 451 | "payable":false, 452 | "stateMutability":"view", 453 | "type":"function" 454 | }, 455 | { 456 | "constant":true, 457 | "inputs":[ 458 | 459 | ], 460 | "name":"basisPointsRate", 461 | "outputs":[ 462 | { 463 | "name":"", 464 | "type":"uint256" 465 | } 466 | ], 467 | "payable":false, 468 | "stateMutability":"view", 469 | "type":"function" 470 | }, 471 | { 472 | "constant":true, 473 | "inputs":[ 474 | { 475 | "name":"", 476 | "type":"address" 477 | } 478 | ], 479 | "name":"isBlackListed", 480 | "outputs":[ 481 | { 482 | "name":"", 483 | "type":"bool" 484 | } 485 | ], 486 | "payable":false, 487 | "stateMutability":"view", 488 | "type":"function" 489 | }, 490 | { 491 | "constant":false, 492 | "inputs":[ 493 | { 494 | "name":"_clearedUser", 495 | "type":"address" 496 | } 497 | ], 498 | "name":"removeBlackList", 499 | "outputs":[ 500 | 501 | ], 502 | "payable":false, 503 | "stateMutability":"nonpayable", 504 | "type":"function" 505 | }, 506 | { 507 | "constant":true, 508 | "inputs":[ 509 | 510 | ], 511 | "name":"MAX_UINT", 512 | "outputs":[ 513 | { 514 | "name":"", 515 | "type":"uint256" 516 | } 517 | ], 518 | "payable":false, 519 | "stateMutability":"view", 520 | "type":"function" 521 | }, 522 | { 523 | "constant":false, 524 | "inputs":[ 525 | { 526 | "name":"newOwner", 527 | "type":"address" 528 | } 529 | ], 530 | "name":"transferOwnership", 531 | "outputs":[ 532 | 533 | ], 534 | "payable":false, 535 | "stateMutability":"nonpayable", 536 | "type":"function" 537 | }, 538 | { 539 | "constant":false, 540 | "inputs":[ 541 | { 542 | "name":"_blackListedUser", 543 | "type":"address" 544 | } 545 | ], 546 | "name":"destroyBlackFunds", 547 | "outputs":[ 548 | 549 | ], 550 | "payable":false, 551 | "stateMutability":"nonpayable", 552 | "type":"function" 553 | }, 554 | { 555 | "inputs":[ 556 | { 557 | "name":"_initialSupply", 558 | "type":"uint256" 559 | }, 560 | { 561 | "name":"_name", 562 | "type":"string" 563 | }, 564 | { 565 | "name":"_symbol", 566 | "type":"string" 567 | }, 568 | { 569 | "name":"_decimals", 570 | "type":"uint256" 571 | } 572 | ], 573 | "payable":false, 574 | "stateMutability":"nonpayable", 575 | "type":"constructor" 576 | }, 577 | { 578 | "anonymous":false, 579 | "inputs":[ 580 | { 581 | "indexed":false, 582 | "name":"amount", 583 | "type":"uint256" 584 | } 585 | ], 586 | "name":"Issue", 587 | "type":"event" 588 | }, 589 | { 590 | "anonymous":false, 591 | "inputs":[ 592 | { 593 | "indexed":false, 594 | "name":"amount", 595 | "type":"uint256" 596 | } 597 | ], 598 | "name":"Redeem", 599 | "type":"event" 600 | }, 601 | { 602 | "anonymous":false, 603 | "inputs":[ 604 | { 605 | "indexed":false, 606 | "name":"newAddress", 607 | "type":"address" 608 | } 609 | ], 610 | "name":"Deprecate", 611 | "type":"event" 612 | }, 613 | { 614 | "anonymous":false, 615 | "inputs":[ 616 | { 617 | "indexed":false, 618 | "name":"feeBasisPoints", 619 | "type":"uint256" 620 | }, 621 | { 622 | "indexed":false, 623 | "name":"maxFee", 624 | "type":"uint256" 625 | } 626 | ], 627 | "name":"Params", 628 | "type":"event" 629 | }, 630 | { 631 | "anonymous":false, 632 | "inputs":[ 633 | { 634 | "indexed":false, 635 | "name":"_blackListedUser", 636 | "type":"address" 637 | }, 638 | { 639 | "indexed":false, 640 | "name":"_balance", 641 | "type":"uint256" 642 | } 643 | ], 644 | "name":"DestroyedBlackFunds", 645 | "type":"event" 646 | }, 647 | { 648 | "anonymous":false, 649 | "inputs":[ 650 | { 651 | "indexed":false, 652 | "name":"_user", 653 | "type":"address" 654 | } 655 | ], 656 | "name":"AddedBlackList", 657 | "type":"event" 658 | }, 659 | { 660 | "anonymous":false, 661 | "inputs":[ 662 | { 663 | "indexed":false, 664 | "name":"_user", 665 | "type":"address" 666 | } 667 | ], 668 | "name":"RemovedBlackList", 669 | "type":"event" 670 | }, 671 | { 672 | "anonymous":false, 673 | "inputs":[ 674 | { 675 | "indexed":true, 676 | "name":"owner", 677 | "type":"address" 678 | }, 679 | { 680 | "indexed":true, 681 | "name":"spender", 682 | "type":"address" 683 | }, 684 | { 685 | "indexed":false, 686 | "name":"value", 687 | "type":"uint256" 688 | } 689 | ], 690 | "name":"Approval", 691 | "type":"event" 692 | }, 693 | { 694 | "anonymous":false, 695 | "inputs":[ 696 | { 697 | "indexed":true, 698 | "name":"from", 699 | "type":"address" 700 | }, 701 | { 702 | "indexed":true, 703 | "name":"to", 704 | "type":"address" 705 | }, 706 | { 707 | "indexed":false, 708 | "name":"value", 709 | "type":"uint256" 710 | } 711 | ], 712 | "name":"Transfer", 713 | "type":"event" 714 | }, 715 | { 716 | "anonymous":false, 717 | "inputs":[ 718 | 719 | ], 720 | "name":"Pause", 721 | "type":"event" 722 | }, 723 | { 724 | "anonymous":false, 725 | "inputs":[ 726 | 727 | ], 728 | "name":"Unpause", 729 | "type":"event" 730 | } 731 | ] -------------------------------------------------------------------------------- /src/test/resources/abiFiles/UniswapV2Router02.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs": [ 4 | { 5 | "internalType": "address", 6 | "name": "_factory", 7 | "type": "address" 8 | }, 9 | { 10 | "internalType": "address", 11 | "name": "_WETH", 12 | "type": "address" 13 | } 14 | ], 15 | "stateMutability": "nonpayable", 16 | "type": "constructor" 17 | }, 18 | { 19 | "inputs": [], 20 | "name": "WETH", 21 | "outputs": [ 22 | { 23 | "internalType": "address", 24 | "name": "", 25 | "type": "address" 26 | } 27 | ], 28 | "stateMutability": "view", 29 | "type": "function" 30 | }, 31 | { 32 | "inputs": [ 33 | { 34 | "internalType": "address", 35 | "name": "tokenA", 36 | "type": "address" 37 | }, 38 | { 39 | "internalType": "address", 40 | "name": "tokenB", 41 | "type": "address" 42 | }, 43 | { 44 | "internalType": "uint256", 45 | "name": "amountADesired", 46 | "type": "uint256" 47 | }, 48 | { 49 | "internalType": "uint256", 50 | "name": "amountBDesired", 51 | "type": "uint256" 52 | }, 53 | { 54 | "internalType": "uint256", 55 | "name": "amountAMin", 56 | "type": "uint256" 57 | }, 58 | { 59 | "internalType": "uint256", 60 | "name": "amountBMin", 61 | "type": "uint256" 62 | }, 63 | { 64 | "internalType": "address", 65 | "name": "to", 66 | "type": "address" 67 | }, 68 | { 69 | "internalType": "uint256", 70 | "name": "deadline", 71 | "type": "uint256" 72 | } 73 | ], 74 | "name": "addLiquidity", 75 | "outputs": [ 76 | { 77 | "internalType": "uint256", 78 | "name": "amountA", 79 | "type": "uint256" 80 | }, 81 | { 82 | "internalType": "uint256", 83 | "name": "amountB", 84 | "type": "uint256" 85 | }, 86 | { 87 | "internalType": "uint256", 88 | "name": "liquidity", 89 | "type": "uint256" 90 | } 91 | ], 92 | "stateMutability": "nonpayable", 93 | "type": "function" 94 | }, 95 | { 96 | "inputs": [ 97 | { 98 | "internalType": "address", 99 | "name": "token", 100 | "type": "address" 101 | }, 102 | { 103 | "internalType": "uint256", 104 | "name": "amountTokenDesired", 105 | "type": "uint256" 106 | }, 107 | { 108 | "internalType": "uint256", 109 | "name": "amountTokenMin", 110 | "type": "uint256" 111 | }, 112 | { 113 | "internalType": "uint256", 114 | "name": "amountETHMin", 115 | "type": "uint256" 116 | }, 117 | { 118 | "internalType": "address", 119 | "name": "to", 120 | "type": "address" 121 | }, 122 | { 123 | "internalType": "uint256", 124 | "name": "deadline", 125 | "type": "uint256" 126 | } 127 | ], 128 | "name": "addLiquidityETH", 129 | "outputs": [ 130 | { 131 | "internalType": "uint256", 132 | "name": "amountToken", 133 | "type": "uint256" 134 | }, 135 | { 136 | "internalType": "uint256", 137 | "name": "amountETH", 138 | "type": "uint256" 139 | }, 140 | { 141 | "internalType": "uint256", 142 | "name": "liquidity", 143 | "type": "uint256" 144 | } 145 | ], 146 | "stateMutability": "payable", 147 | "type": "function" 148 | }, 149 | { 150 | "inputs": [], 151 | "name": "factory", 152 | "outputs": [ 153 | { 154 | "internalType": "address", 155 | "name": "", 156 | "type": "address" 157 | } 158 | ], 159 | "stateMutability": "view", 160 | "type": "function" 161 | }, 162 | { 163 | "inputs": [ 164 | { 165 | "internalType": "uint256", 166 | "name": "amountOut", 167 | "type": "uint256" 168 | }, 169 | { 170 | "internalType": "uint256", 171 | "name": "reserveIn", 172 | "type": "uint256" 173 | }, 174 | { 175 | "internalType": "uint256", 176 | "name": "reserveOut", 177 | "type": "uint256" 178 | } 179 | ], 180 | "name": "getAmountIn", 181 | "outputs": [ 182 | { 183 | "internalType": "uint256", 184 | "name": "amountIn", 185 | "type": "uint256" 186 | } 187 | ], 188 | "stateMutability": "pure", 189 | "type": "function" 190 | }, 191 | { 192 | "inputs": [ 193 | { 194 | "internalType": "uint256", 195 | "name": "amountIn", 196 | "type": "uint256" 197 | }, 198 | { 199 | "internalType": "uint256", 200 | "name": "reserveIn", 201 | "type": "uint256" 202 | }, 203 | { 204 | "internalType": "uint256", 205 | "name": "reserveOut", 206 | "type": "uint256" 207 | } 208 | ], 209 | "name": "getAmountOut", 210 | "outputs": [ 211 | { 212 | "internalType": "uint256", 213 | "name": "amountOut", 214 | "type": "uint256" 215 | } 216 | ], 217 | "stateMutability": "pure", 218 | "type": "function" 219 | }, 220 | { 221 | "inputs": [ 222 | { 223 | "internalType": "uint256", 224 | "name": "amountOut", 225 | "type": "uint256" 226 | }, 227 | { 228 | "internalType": "address[]", 229 | "name": "path", 230 | "type": "address[]" 231 | } 232 | ], 233 | "name": "getAmountsIn", 234 | "outputs": [ 235 | { 236 | "internalType": "uint256[]", 237 | "name": "amounts", 238 | "type": "uint256[]" 239 | } 240 | ], 241 | "stateMutability": "view", 242 | "type": "function" 243 | }, 244 | { 245 | "inputs": [ 246 | { 247 | "internalType": "uint256", 248 | "name": "amountIn", 249 | "type": "uint256" 250 | }, 251 | { 252 | "internalType": "address[]", 253 | "name": "path", 254 | "type": "address[]" 255 | } 256 | ], 257 | "name": "getAmountsOut", 258 | "outputs": [ 259 | { 260 | "internalType": "uint256[]", 261 | "name": "amounts", 262 | "type": "uint256[]" 263 | } 264 | ], 265 | "stateMutability": "view", 266 | "type": "function" 267 | }, 268 | { 269 | "inputs": [ 270 | { 271 | "internalType": "uint256", 272 | "name": "amountA", 273 | "type": "uint256" 274 | }, 275 | { 276 | "internalType": "uint256", 277 | "name": "reserveA", 278 | "type": "uint256" 279 | }, 280 | { 281 | "internalType": "uint256", 282 | "name": "reserveB", 283 | "type": "uint256" 284 | } 285 | ], 286 | "name": "quote", 287 | "outputs": [ 288 | { 289 | "internalType": "uint256", 290 | "name": "amountB", 291 | "type": "uint256" 292 | } 293 | ], 294 | "stateMutability": "pure", 295 | "type": "function" 296 | }, 297 | { 298 | "inputs": [ 299 | { 300 | "internalType": "address", 301 | "name": "tokenA", 302 | "type": "address" 303 | }, 304 | { 305 | "internalType": "address", 306 | "name": "tokenB", 307 | "type": "address" 308 | }, 309 | { 310 | "internalType": "uint256", 311 | "name": "liquidity", 312 | "type": "uint256" 313 | }, 314 | { 315 | "internalType": "uint256", 316 | "name": "amountAMin", 317 | "type": "uint256" 318 | }, 319 | { 320 | "internalType": "uint256", 321 | "name": "amountBMin", 322 | "type": "uint256" 323 | }, 324 | { 325 | "internalType": "address", 326 | "name": "to", 327 | "type": "address" 328 | }, 329 | { 330 | "internalType": "uint256", 331 | "name": "deadline", 332 | "type": "uint256" 333 | } 334 | ], 335 | "name": "removeLiquidity", 336 | "outputs": [ 337 | { 338 | "internalType": "uint256", 339 | "name": "amountA", 340 | "type": "uint256" 341 | }, 342 | { 343 | "internalType": "uint256", 344 | "name": "amountB", 345 | "type": "uint256" 346 | } 347 | ], 348 | "stateMutability": "nonpayable", 349 | "type": "function" 350 | }, 351 | { 352 | "inputs": [ 353 | { 354 | "internalType": "address", 355 | "name": "token", 356 | "type": "address" 357 | }, 358 | { 359 | "internalType": "uint256", 360 | "name": "liquidity", 361 | "type": "uint256" 362 | }, 363 | { 364 | "internalType": "uint256", 365 | "name": "amountTokenMin", 366 | "type": "uint256" 367 | }, 368 | { 369 | "internalType": "uint256", 370 | "name": "amountETHMin", 371 | "type": "uint256" 372 | }, 373 | { 374 | "internalType": "address", 375 | "name": "to", 376 | "type": "address" 377 | }, 378 | { 379 | "internalType": "uint256", 380 | "name": "deadline", 381 | "type": "uint256" 382 | } 383 | ], 384 | "name": "removeLiquidityETH", 385 | "outputs": [ 386 | { 387 | "internalType": "uint256", 388 | "name": "amountToken", 389 | "type": "uint256" 390 | }, 391 | { 392 | "internalType": "uint256", 393 | "name": "amountETH", 394 | "type": "uint256" 395 | } 396 | ], 397 | "stateMutability": "nonpayable", 398 | "type": "function" 399 | }, 400 | { 401 | "inputs": [ 402 | { 403 | "internalType": "address", 404 | "name": "token", 405 | "type": "address" 406 | }, 407 | { 408 | "internalType": "uint256", 409 | "name": "liquidity", 410 | "type": "uint256" 411 | }, 412 | { 413 | "internalType": "uint256", 414 | "name": "amountTokenMin", 415 | "type": "uint256" 416 | }, 417 | { 418 | "internalType": "uint256", 419 | "name": "amountETHMin", 420 | "type": "uint256" 421 | }, 422 | { 423 | "internalType": "address", 424 | "name": "to", 425 | "type": "address" 426 | }, 427 | { 428 | "internalType": "uint256", 429 | "name": "deadline", 430 | "type": "uint256" 431 | } 432 | ], 433 | "name": "removeLiquidityETHSupportingFeeOnTransferTokens", 434 | "outputs": [ 435 | { 436 | "internalType": "uint256", 437 | "name": "amountETH", 438 | "type": "uint256" 439 | } 440 | ], 441 | "stateMutability": "nonpayable", 442 | "type": "function" 443 | }, 444 | { 445 | "inputs": [ 446 | { 447 | "internalType": "address", 448 | "name": "token", 449 | "type": "address" 450 | }, 451 | { 452 | "internalType": "uint256", 453 | "name": "liquidity", 454 | "type": "uint256" 455 | }, 456 | { 457 | "internalType": "uint256", 458 | "name": "amountTokenMin", 459 | "type": "uint256" 460 | }, 461 | { 462 | "internalType": "uint256", 463 | "name": "amountETHMin", 464 | "type": "uint256" 465 | }, 466 | { 467 | "internalType": "address", 468 | "name": "to", 469 | "type": "address" 470 | }, 471 | { 472 | "internalType": "uint256", 473 | "name": "deadline", 474 | "type": "uint256" 475 | }, 476 | { 477 | "internalType": "bool", 478 | "name": "approveMax", 479 | "type": "bool" 480 | }, 481 | { 482 | "internalType": "uint8", 483 | "name": "v", 484 | "type": "uint8" 485 | }, 486 | { 487 | "internalType": "bytes32", 488 | "name": "r", 489 | "type": "bytes32" 490 | }, 491 | { 492 | "internalType": "bytes32", 493 | "name": "s", 494 | "type": "bytes32" 495 | } 496 | ], 497 | "name": "removeLiquidityETHWithPermit", 498 | "outputs": [ 499 | { 500 | "internalType": "uint256", 501 | "name": "amountToken", 502 | "type": "uint256" 503 | }, 504 | { 505 | "internalType": "uint256", 506 | "name": "amountETH", 507 | "type": "uint256" 508 | } 509 | ], 510 | "stateMutability": "nonpayable", 511 | "type": "function" 512 | }, 513 | { 514 | "inputs": [ 515 | { 516 | "internalType": "address", 517 | "name": "token", 518 | "type": "address" 519 | }, 520 | { 521 | "internalType": "uint256", 522 | "name": "liquidity", 523 | "type": "uint256" 524 | }, 525 | { 526 | "internalType": "uint256", 527 | "name": "amountTokenMin", 528 | "type": "uint256" 529 | }, 530 | { 531 | "internalType": "uint256", 532 | "name": "amountETHMin", 533 | "type": "uint256" 534 | }, 535 | { 536 | "internalType": "address", 537 | "name": "to", 538 | "type": "address" 539 | }, 540 | { 541 | "internalType": "uint256", 542 | "name": "deadline", 543 | "type": "uint256" 544 | }, 545 | { 546 | "internalType": "bool", 547 | "name": "approveMax", 548 | "type": "bool" 549 | }, 550 | { 551 | "internalType": "uint8", 552 | "name": "v", 553 | "type": "uint8" 554 | }, 555 | { 556 | "internalType": "bytes32", 557 | "name": "r", 558 | "type": "bytes32" 559 | }, 560 | { 561 | "internalType": "bytes32", 562 | "name": "s", 563 | "type": "bytes32" 564 | } 565 | ], 566 | "name": "removeLiquidityETHWithPermitSupportingFeeOnTransferTokens", 567 | "outputs": [ 568 | { 569 | "internalType": "uint256", 570 | "name": "amountETH", 571 | "type": "uint256" 572 | } 573 | ], 574 | "stateMutability": "nonpayable", 575 | "type": "function" 576 | }, 577 | { 578 | "inputs": [ 579 | { 580 | "internalType": "address", 581 | "name": "tokenA", 582 | "type": "address" 583 | }, 584 | { 585 | "internalType": "address", 586 | "name": "tokenB", 587 | "type": "address" 588 | }, 589 | { 590 | "internalType": "uint256", 591 | "name": "liquidity", 592 | "type": "uint256" 593 | }, 594 | { 595 | "internalType": "uint256", 596 | "name": "amountAMin", 597 | "type": "uint256" 598 | }, 599 | { 600 | "internalType": "uint256", 601 | "name": "amountBMin", 602 | "type": "uint256" 603 | }, 604 | { 605 | "internalType": "address", 606 | "name": "to", 607 | "type": "address" 608 | }, 609 | { 610 | "internalType": "uint256", 611 | "name": "deadline", 612 | "type": "uint256" 613 | }, 614 | { 615 | "internalType": "bool", 616 | "name": "approveMax", 617 | "type": "bool" 618 | }, 619 | { 620 | "internalType": "uint8", 621 | "name": "v", 622 | "type": "uint8" 623 | }, 624 | { 625 | "internalType": "bytes32", 626 | "name": "r", 627 | "type": "bytes32" 628 | }, 629 | { 630 | "internalType": "bytes32", 631 | "name": "s", 632 | "type": "bytes32" 633 | } 634 | ], 635 | "name": "removeLiquidityWithPermit", 636 | "outputs": [ 637 | { 638 | "internalType": "uint256", 639 | "name": "amountA", 640 | "type": "uint256" 641 | }, 642 | { 643 | "internalType": "uint256", 644 | "name": "amountB", 645 | "type": "uint256" 646 | } 647 | ], 648 | "stateMutability": "nonpayable", 649 | "type": "function" 650 | }, 651 | { 652 | "inputs": [ 653 | { 654 | "internalType": "uint256", 655 | "name": "amountOut", 656 | "type": "uint256" 657 | }, 658 | { 659 | "internalType": "address[]", 660 | "name": "path", 661 | "type": "address[]" 662 | }, 663 | { 664 | "internalType": "address", 665 | "name": "to", 666 | "type": "address" 667 | }, 668 | { 669 | "internalType": "uint256", 670 | "name": "deadline", 671 | "type": "uint256" 672 | } 673 | ], 674 | "name": "swapETHForExactTokens", 675 | "outputs": [ 676 | { 677 | "internalType": "uint256[]", 678 | "name": "amounts", 679 | "type": "uint256[]" 680 | } 681 | ], 682 | "stateMutability": "payable", 683 | "type": "function" 684 | }, 685 | { 686 | "inputs": [ 687 | { 688 | "internalType": "uint256", 689 | "name": "amountOutMin", 690 | "type": "uint256" 691 | }, 692 | { 693 | "internalType": "address[]", 694 | "name": "path", 695 | "type": "address[]" 696 | }, 697 | { 698 | "internalType": "address", 699 | "name": "to", 700 | "type": "address" 701 | }, 702 | { 703 | "internalType": "uint256", 704 | "name": "deadline", 705 | "type": "uint256" 706 | } 707 | ], 708 | "name": "swapExactETHForTokens", 709 | "outputs": [ 710 | { 711 | "internalType": "uint256[]", 712 | "name": "amounts", 713 | "type": "uint256[]" 714 | } 715 | ], 716 | "stateMutability": "payable", 717 | "type": "function" 718 | }, 719 | { 720 | "inputs": [ 721 | { 722 | "internalType": "uint256", 723 | "name": "amountOutMin", 724 | "type": "uint256" 725 | }, 726 | { 727 | "internalType": "address[]", 728 | "name": "path", 729 | "type": "address[]" 730 | }, 731 | { 732 | "internalType": "address", 733 | "name": "to", 734 | "type": "address" 735 | }, 736 | { 737 | "internalType": "uint256", 738 | "name": "deadline", 739 | "type": "uint256" 740 | } 741 | ], 742 | "name": "swapExactETHForTokensSupportingFeeOnTransferTokens", 743 | "outputs": [], 744 | "stateMutability": "payable", 745 | "type": "function" 746 | }, 747 | { 748 | "inputs": [ 749 | { 750 | "internalType": "uint256", 751 | "name": "amountIn", 752 | "type": "uint256" 753 | }, 754 | { 755 | "internalType": "uint256", 756 | "name": "amountOutMin", 757 | "type": "uint256" 758 | }, 759 | { 760 | "internalType": "address[]", 761 | "name": "path", 762 | "type": "address[]" 763 | }, 764 | { 765 | "internalType": "address", 766 | "name": "to", 767 | "type": "address" 768 | }, 769 | { 770 | "internalType": "uint256", 771 | "name": "deadline", 772 | "type": "uint256" 773 | } 774 | ], 775 | "name": "swapExactTokensForETH", 776 | "outputs": [ 777 | { 778 | "internalType": "uint256[]", 779 | "name": "amounts", 780 | "type": "uint256[]" 781 | } 782 | ], 783 | "stateMutability": "nonpayable", 784 | "type": "function" 785 | }, 786 | { 787 | "inputs": [ 788 | { 789 | "internalType": "uint256", 790 | "name": "amountIn", 791 | "type": "uint256" 792 | }, 793 | { 794 | "internalType": "uint256", 795 | "name": "amountOutMin", 796 | "type": "uint256" 797 | }, 798 | { 799 | "internalType": "address[]", 800 | "name": "path", 801 | "type": "address[]" 802 | }, 803 | { 804 | "internalType": "address", 805 | "name": "to", 806 | "type": "address" 807 | }, 808 | { 809 | "internalType": "uint256", 810 | "name": "deadline", 811 | "type": "uint256" 812 | } 813 | ], 814 | "name": "swapExactTokensForETHSupportingFeeOnTransferTokens", 815 | "outputs": [], 816 | "stateMutability": "nonpayable", 817 | "type": "function" 818 | }, 819 | { 820 | "inputs": [ 821 | { 822 | "internalType": "uint256", 823 | "name": "amountIn", 824 | "type": "uint256" 825 | }, 826 | { 827 | "internalType": "uint256", 828 | "name": "amountOutMin", 829 | "type": "uint256" 830 | }, 831 | { 832 | "internalType": "address[]", 833 | "name": "path", 834 | "type": "address[]" 835 | }, 836 | { 837 | "internalType": "address", 838 | "name": "to", 839 | "type": "address" 840 | }, 841 | { 842 | "internalType": "uint256", 843 | "name": "deadline", 844 | "type": "uint256" 845 | } 846 | ], 847 | "name": "swapExactTokensForTokens", 848 | "outputs": [ 849 | { 850 | "internalType": "uint256[]", 851 | "name": "amounts", 852 | "type": "uint256[]" 853 | } 854 | ], 855 | "stateMutability": "nonpayable", 856 | "type": "function" 857 | }, 858 | { 859 | "inputs": [ 860 | { 861 | "internalType": "uint256", 862 | "name": "amountIn", 863 | "type": "uint256" 864 | }, 865 | { 866 | "internalType": "uint256", 867 | "name": "amountOutMin", 868 | "type": "uint256" 869 | }, 870 | { 871 | "internalType": "address[]", 872 | "name": "path", 873 | "type": "address[]" 874 | }, 875 | { 876 | "internalType": "address", 877 | "name": "to", 878 | "type": "address" 879 | }, 880 | { 881 | "internalType": "uint256", 882 | "name": "deadline", 883 | "type": "uint256" 884 | } 885 | ], 886 | "name": "swapExactTokensForTokensSupportingFeeOnTransferTokens", 887 | "outputs": [], 888 | "stateMutability": "nonpayable", 889 | "type": "function" 890 | }, 891 | { 892 | "inputs": [ 893 | { 894 | "internalType": "uint256", 895 | "name": "amountOut", 896 | "type": "uint256" 897 | }, 898 | { 899 | "internalType": "uint256", 900 | "name": "amountInMax", 901 | "type": "uint256" 902 | }, 903 | { 904 | "internalType": "address[]", 905 | "name": "path", 906 | "type": "address[]" 907 | }, 908 | { 909 | "internalType": "address", 910 | "name": "to", 911 | "type": "address" 912 | }, 913 | { 914 | "internalType": "uint256", 915 | "name": "deadline", 916 | "type": "uint256" 917 | } 918 | ], 919 | "name": "swapTokensForExactETH", 920 | "outputs": [ 921 | { 922 | "internalType": "uint256[]", 923 | "name": "amounts", 924 | "type": "uint256[]" 925 | } 926 | ], 927 | "stateMutability": "nonpayable", 928 | "type": "function" 929 | }, 930 | { 931 | "inputs": [ 932 | { 933 | "internalType": "uint256", 934 | "name": "amountOut", 935 | "type": "uint256" 936 | }, 937 | { 938 | "internalType": "uint256", 939 | "name": "amountInMax", 940 | "type": "uint256" 941 | }, 942 | { 943 | "internalType": "address[]", 944 | "name": "path", 945 | "type": "address[]" 946 | }, 947 | { 948 | "internalType": "address", 949 | "name": "to", 950 | "type": "address" 951 | }, 952 | { 953 | "internalType": "uint256", 954 | "name": "deadline", 955 | "type": "uint256" 956 | } 957 | ], 958 | "name": "swapTokensForExactTokens", 959 | "outputs": [ 960 | { 961 | "internalType": "uint256[]", 962 | "name": "amounts", 963 | "type": "uint256[]" 964 | } 965 | ], 966 | "stateMutability": "nonpayable", 967 | "type": "function" 968 | } 969 | ] -------------------------------------------------------------------------------- /src/test/resources/abiFiles/UniswapV3Router.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs":[ 4 | { 5 | "internalType":"address", 6 | "name":"_factory", 7 | "type":"address" 8 | }, 9 | { 10 | "internalType":"address", 11 | "name":"_WETH9", 12 | "type":"address" 13 | } 14 | ], 15 | "stateMutability":"nonpayable", 16 | "type":"constructor" 17 | }, 18 | { 19 | "inputs":[ 20 | 21 | ], 22 | "name":"WETH9", 23 | "outputs":[ 24 | { 25 | "internalType":"address", 26 | "name":"", 27 | "type":"address" 28 | } 29 | ], 30 | "stateMutability":"view", 31 | "type":"function" 32 | }, 33 | { 34 | "inputs":[ 35 | { 36 | "components":[ 37 | { 38 | "internalType":"bytes", 39 | "name":"path", 40 | "type":"bytes" 41 | }, 42 | { 43 | "internalType":"address", 44 | "name":"recipient", 45 | "type":"address" 46 | }, 47 | { 48 | "internalType":"uint256", 49 | "name":"deadline", 50 | "type":"uint256" 51 | }, 52 | { 53 | "internalType":"uint256", 54 | "name":"amountIn", 55 | "type":"uint256" 56 | }, 57 | { 58 | "internalType":"uint256", 59 | "name":"amountOutMinimum", 60 | "type":"uint256" 61 | } 62 | ], 63 | "internalType":"struct ISwapRouter.ExactInputParams", 64 | "name":"params", 65 | "type":"tuple" 66 | } 67 | ], 68 | "name":"exactInput", 69 | "outputs":[ 70 | { 71 | "internalType":"uint256", 72 | "name":"amountOut", 73 | "type":"uint256" 74 | } 75 | ], 76 | "stateMutability":"payable", 77 | "type":"function" 78 | }, 79 | { 80 | "inputs":[ 81 | { 82 | "components":[ 83 | { 84 | "internalType":"address", 85 | "name":"tokenIn", 86 | "type":"address" 87 | }, 88 | { 89 | "internalType":"address", 90 | "name":"tokenOut", 91 | "type":"address" 92 | }, 93 | { 94 | "internalType":"uint24", 95 | "name":"fee", 96 | "type":"uint24" 97 | }, 98 | { 99 | "internalType":"address", 100 | "name":"recipient", 101 | "type":"address" 102 | }, 103 | { 104 | "internalType":"uint256", 105 | "name":"deadline", 106 | "type":"uint256" 107 | }, 108 | { 109 | "internalType":"uint256", 110 | "name":"amountIn", 111 | "type":"uint256" 112 | }, 113 | { 114 | "internalType":"uint256", 115 | "name":"amountOutMinimum", 116 | "type":"uint256" 117 | }, 118 | { 119 | "internalType":"uint160", 120 | "name":"sqrtPriceLimitX96", 121 | "type":"uint160" 122 | } 123 | ], 124 | "internalType":"struct ISwapRouter.ExactInputSingleParams", 125 | "name":"params", 126 | "type":"tuple" 127 | } 128 | ], 129 | "name":"exactInputSingle", 130 | "outputs":[ 131 | { 132 | "internalType":"uint256", 133 | "name":"amountOut", 134 | "type":"uint256" 135 | } 136 | ], 137 | "stateMutability":"payable", 138 | "type":"function" 139 | }, 140 | { 141 | "inputs":[ 142 | { 143 | "components":[ 144 | { 145 | "internalType":"bytes", 146 | "name":"path", 147 | "type":"bytes" 148 | }, 149 | { 150 | "internalType":"address", 151 | "name":"recipient", 152 | "type":"address" 153 | }, 154 | { 155 | "internalType":"uint256", 156 | "name":"deadline", 157 | "type":"uint256" 158 | }, 159 | { 160 | "internalType":"uint256", 161 | "name":"amountOut", 162 | "type":"uint256" 163 | }, 164 | { 165 | "internalType":"uint256", 166 | "name":"amountInMaximum", 167 | "type":"uint256" 168 | } 169 | ], 170 | "internalType":"struct ISwapRouter.ExactOutputParams", 171 | "name":"params", 172 | "type":"tuple" 173 | } 174 | ], 175 | "name":"exactOutput", 176 | "outputs":[ 177 | { 178 | "internalType":"uint256", 179 | "name":"amountIn", 180 | "type":"uint256" 181 | } 182 | ], 183 | "stateMutability":"payable", 184 | "type":"function" 185 | }, 186 | { 187 | "inputs":[ 188 | { 189 | "components":[ 190 | { 191 | "internalType":"address", 192 | "name":"tokenIn", 193 | "type":"address" 194 | }, 195 | { 196 | "internalType":"address", 197 | "name":"tokenOut", 198 | "type":"address" 199 | }, 200 | { 201 | "internalType":"uint24", 202 | "name":"fee", 203 | "type":"uint24" 204 | }, 205 | { 206 | "internalType":"address", 207 | "name":"recipient", 208 | "type":"address" 209 | }, 210 | { 211 | "internalType":"uint256", 212 | "name":"deadline", 213 | "type":"uint256" 214 | }, 215 | { 216 | "internalType":"uint256", 217 | "name":"amountOut", 218 | "type":"uint256" 219 | }, 220 | { 221 | "internalType":"uint256", 222 | "name":"amountInMaximum", 223 | "type":"uint256" 224 | }, 225 | { 226 | "internalType":"uint160", 227 | "name":"sqrtPriceLimitX96", 228 | "type":"uint160" 229 | } 230 | ], 231 | "internalType":"struct ISwapRouter.ExactOutputSingleParams", 232 | "name":"params", 233 | "type":"tuple" 234 | } 235 | ], 236 | "name":"exactOutputSingle", 237 | "outputs":[ 238 | { 239 | "internalType":"uint256", 240 | "name":"amountIn", 241 | "type":"uint256" 242 | } 243 | ], 244 | "stateMutability":"payable", 245 | "type":"function" 246 | }, 247 | { 248 | "inputs":[ 249 | 250 | ], 251 | "name":"factory", 252 | "outputs":[ 253 | { 254 | "internalType":"address", 255 | "name":"", 256 | "type":"address" 257 | } 258 | ], 259 | "stateMutability":"view", 260 | "type":"function" 261 | }, 262 | { 263 | "inputs":[ 264 | { 265 | "internalType":"bytes[]", 266 | "name":"data", 267 | "type":"bytes[]" 268 | } 269 | ], 270 | "name":"multicall", 271 | "outputs":[ 272 | { 273 | "internalType":"bytes[]", 274 | "name":"results", 275 | "type":"bytes[]" 276 | } 277 | ], 278 | "stateMutability":"payable", 279 | "type":"function" 280 | }, 281 | { 282 | "inputs":[ 283 | 284 | ], 285 | "name":"refundETH", 286 | "outputs":[ 287 | 288 | ], 289 | "stateMutability":"payable", 290 | "type":"function" 291 | }, 292 | { 293 | "inputs":[ 294 | { 295 | "internalType":"address", 296 | "name":"token", 297 | "type":"address" 298 | }, 299 | { 300 | "internalType":"uint256", 301 | "name":"value", 302 | "type":"uint256" 303 | }, 304 | { 305 | "internalType":"uint256", 306 | "name":"deadline", 307 | "type":"uint256" 308 | }, 309 | { 310 | "internalType":"uint8", 311 | "name":"v", 312 | "type":"uint8" 313 | }, 314 | { 315 | "internalType":"bytes32", 316 | "name":"r", 317 | "type":"bytes32" 318 | }, 319 | { 320 | "internalType":"bytes32", 321 | "name":"s", 322 | "type":"bytes32" 323 | } 324 | ], 325 | "name":"selfPermit", 326 | "outputs":[ 327 | 328 | ], 329 | "stateMutability":"payable", 330 | "type":"function" 331 | }, 332 | { 333 | "inputs":[ 334 | { 335 | "internalType":"address", 336 | "name":"token", 337 | "type":"address" 338 | }, 339 | { 340 | "internalType":"uint256", 341 | "name":"nonce", 342 | "type":"uint256" 343 | }, 344 | { 345 | "internalType":"uint256", 346 | "name":"expiry", 347 | "type":"uint256" 348 | }, 349 | { 350 | "internalType":"uint8", 351 | "name":"v", 352 | "type":"uint8" 353 | }, 354 | { 355 | "internalType":"bytes32", 356 | "name":"r", 357 | "type":"bytes32" 358 | }, 359 | { 360 | "internalType":"bytes32", 361 | "name":"s", 362 | "type":"bytes32" 363 | } 364 | ], 365 | "name":"selfPermitAllowed", 366 | "outputs":[ 367 | 368 | ], 369 | "stateMutability":"payable", 370 | "type":"function" 371 | }, 372 | { 373 | "inputs":[ 374 | { 375 | "internalType":"address", 376 | "name":"token", 377 | "type":"address" 378 | }, 379 | { 380 | "internalType":"uint256", 381 | "name":"nonce", 382 | "type":"uint256" 383 | }, 384 | { 385 | "internalType":"uint256", 386 | "name":"expiry", 387 | "type":"uint256" 388 | }, 389 | { 390 | "internalType":"uint8", 391 | "name":"v", 392 | "type":"uint8" 393 | }, 394 | { 395 | "internalType":"bytes32", 396 | "name":"r", 397 | "type":"bytes32" 398 | }, 399 | { 400 | "internalType":"bytes32", 401 | "name":"s", 402 | "type":"bytes32" 403 | } 404 | ], 405 | "name":"selfPermitAllowedIfNecessary", 406 | "outputs":[ 407 | 408 | ], 409 | "stateMutability":"payable", 410 | "type":"function" 411 | }, 412 | { 413 | "inputs":[ 414 | { 415 | "internalType":"address", 416 | "name":"token", 417 | "type":"address" 418 | }, 419 | { 420 | "internalType":"uint256", 421 | "name":"value", 422 | "type":"uint256" 423 | }, 424 | { 425 | "internalType":"uint256", 426 | "name":"deadline", 427 | "type":"uint256" 428 | }, 429 | { 430 | "internalType":"uint8", 431 | "name":"v", 432 | "type":"uint8" 433 | }, 434 | { 435 | "internalType":"bytes32", 436 | "name":"r", 437 | "type":"bytes32" 438 | }, 439 | { 440 | "internalType":"bytes32", 441 | "name":"s", 442 | "type":"bytes32" 443 | } 444 | ], 445 | "name":"selfPermitIfNecessary", 446 | "outputs":[ 447 | 448 | ], 449 | "stateMutability":"payable", 450 | "type":"function" 451 | }, 452 | { 453 | "inputs":[ 454 | { 455 | "internalType":"address", 456 | "name":"token", 457 | "type":"address" 458 | }, 459 | { 460 | "internalType":"uint256", 461 | "name":"amountMinimum", 462 | "type":"uint256" 463 | }, 464 | { 465 | "internalType":"address", 466 | "name":"recipient", 467 | "type":"address" 468 | } 469 | ], 470 | "name":"sweepToken", 471 | "outputs":[ 472 | 473 | ], 474 | "stateMutability":"payable", 475 | "type":"function" 476 | }, 477 | { 478 | "inputs":[ 479 | { 480 | "internalType":"address", 481 | "name":"token", 482 | "type":"address" 483 | }, 484 | { 485 | "internalType":"uint256", 486 | "name":"amountMinimum", 487 | "type":"uint256" 488 | }, 489 | { 490 | "internalType":"address", 491 | "name":"recipient", 492 | "type":"address" 493 | }, 494 | { 495 | "internalType":"uint256", 496 | "name":"feeBips", 497 | "type":"uint256" 498 | }, 499 | { 500 | "internalType":"address", 501 | "name":"feeRecipient", 502 | "type":"address" 503 | } 504 | ], 505 | "name":"sweepTokenWithFee", 506 | "outputs":[ 507 | 508 | ], 509 | "stateMutability":"payable", 510 | "type":"function" 511 | }, 512 | { 513 | "inputs":[ 514 | { 515 | "internalType":"int256", 516 | "name":"amount0Delta", 517 | "type":"int256" 518 | }, 519 | { 520 | "internalType":"int256", 521 | "name":"amount1Delta", 522 | "type":"int256" 523 | }, 524 | { 525 | "internalType":"bytes", 526 | "name":"_data", 527 | "type":"bytes" 528 | } 529 | ], 530 | "name":"uniswapV3SwapCallback", 531 | "outputs":[ 532 | 533 | ], 534 | "stateMutability":"nonpayable", 535 | "type":"function" 536 | }, 537 | { 538 | "inputs":[ 539 | { 540 | "internalType":"uint256", 541 | "name":"amountMinimum", 542 | "type":"uint256" 543 | }, 544 | { 545 | "internalType":"address", 546 | "name":"recipient", 547 | "type":"address" 548 | } 549 | ], 550 | "name":"unwrapWETH9", 551 | "outputs":[ 552 | 553 | ], 554 | "stateMutability":"payable", 555 | "type":"function" 556 | }, 557 | { 558 | "inputs":[ 559 | { 560 | "internalType":"uint256", 561 | "name":"amountMinimum", 562 | "type":"uint256" 563 | }, 564 | { 565 | "internalType":"address", 566 | "name":"recipient", 567 | "type":"address" 568 | }, 569 | { 570 | "internalType":"uint256", 571 | "name":"feeBips", 572 | "type":"uint256" 573 | }, 574 | { 575 | "internalType":"address", 576 | "name":"feeRecipient", 577 | "type":"address" 578 | } 579 | ], 580 | "name":"unwrapWETH9WithFee", 581 | "outputs":[ 582 | 583 | ], 584 | "stateMutability":"payable", 585 | "type":"function" 586 | }, 587 | { 588 | "stateMutability":"payable", 589 | "type":"receive" 590 | } 591 | ] -------------------------------------------------------------------------------- /src/test/resources/abiFiles/UniswapV3SwapRouter.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs":[ 4 | { 5 | "internalType":"address", 6 | "name":"_factory", 7 | "type":"address" 8 | }, 9 | { 10 | "internalType":"address", 11 | "name":"_WETH9", 12 | "type":"address" 13 | } 14 | ], 15 | "stateMutability":"nonpayable", 16 | "type":"constructor" 17 | }, 18 | { 19 | "inputs":[ 20 | 21 | ], 22 | "name":"WETH9", 23 | "outputs":[ 24 | { 25 | "internalType":"address", 26 | "name":"", 27 | "type":"address" 28 | } 29 | ], 30 | "stateMutability":"view", 31 | "type":"function" 32 | }, 33 | { 34 | "inputs":[ 35 | { 36 | "components":[ 37 | { 38 | "internalType":"bytes", 39 | "name":"path", 40 | "type":"bytes" 41 | }, 42 | { 43 | "internalType":"address", 44 | "name":"recipient", 45 | "type":"address" 46 | }, 47 | { 48 | "internalType":"uint256", 49 | "name":"deadline", 50 | "type":"uint256" 51 | }, 52 | { 53 | "internalType":"uint256", 54 | "name":"amountIn", 55 | "type":"uint256" 56 | }, 57 | { 58 | "internalType":"uint256", 59 | "name":"amountOutMinimum", 60 | "type":"uint256" 61 | } 62 | ], 63 | "internalType":"struct ISwapRouter.ExactInputParams", 64 | "name":"params", 65 | "type":"tuple" 66 | } 67 | ], 68 | "name":"exactInput", 69 | "outputs":[ 70 | { 71 | "internalType":"uint256", 72 | "name":"amountOut", 73 | "type":"uint256" 74 | } 75 | ], 76 | "stateMutability":"payable", 77 | "type":"function" 78 | }, 79 | { 80 | "inputs":[ 81 | { 82 | "components":[ 83 | { 84 | "internalType":"address", 85 | "name":"tokenIn", 86 | "type":"address" 87 | }, 88 | { 89 | "internalType":"address", 90 | "name":"tokenOut", 91 | "type":"address" 92 | }, 93 | { 94 | "internalType":"uint24", 95 | "name":"fee", 96 | "type":"uint24" 97 | }, 98 | { 99 | "internalType":"address", 100 | "name":"recipient", 101 | "type":"address" 102 | }, 103 | { 104 | "internalType":"uint256", 105 | "name":"deadline", 106 | "type":"uint256" 107 | }, 108 | { 109 | "internalType":"uint256", 110 | "name":"amountIn", 111 | "type":"uint256" 112 | }, 113 | { 114 | "internalType":"uint256", 115 | "name":"amountOutMinimum", 116 | "type":"uint256" 117 | }, 118 | { 119 | "internalType":"uint160", 120 | "name":"sqrtPriceLimitX96", 121 | "type":"uint160" 122 | } 123 | ], 124 | "internalType":"struct ISwapRouter.ExactInputSingleParams", 125 | "name":"params", 126 | "type":"tuple" 127 | } 128 | ], 129 | "name":"exactInputSingle", 130 | "outputs":[ 131 | { 132 | "internalType":"uint256", 133 | "name":"amountOut", 134 | "type":"uint256" 135 | } 136 | ], 137 | "stateMutability":"payable", 138 | "type":"function" 139 | }, 140 | { 141 | "inputs":[ 142 | { 143 | "components":[ 144 | { 145 | "internalType":"bytes", 146 | "name":"path", 147 | "type":"bytes" 148 | }, 149 | { 150 | "internalType":"address", 151 | "name":"recipient", 152 | "type":"address" 153 | }, 154 | { 155 | "internalType":"uint256", 156 | "name":"deadline", 157 | "type":"uint256" 158 | }, 159 | { 160 | "internalType":"uint256", 161 | "name":"amountOut", 162 | "type":"uint256" 163 | }, 164 | { 165 | "internalType":"uint256", 166 | "name":"amountInMaximum", 167 | "type":"uint256" 168 | } 169 | ], 170 | "internalType":"struct ISwapRouter.ExactOutputParams", 171 | "name":"params", 172 | "type":"tuple" 173 | } 174 | ], 175 | "name":"exactOutput", 176 | "outputs":[ 177 | { 178 | "internalType":"uint256", 179 | "name":"amountIn", 180 | "type":"uint256" 181 | } 182 | ], 183 | "stateMutability":"payable", 184 | "type":"function" 185 | }, 186 | { 187 | "inputs":[ 188 | { 189 | "components":[ 190 | { 191 | "internalType":"address", 192 | "name":"tokenIn", 193 | "type":"address" 194 | }, 195 | { 196 | "internalType":"address", 197 | "name":"tokenOut", 198 | "type":"address" 199 | }, 200 | { 201 | "internalType":"uint24", 202 | "name":"fee", 203 | "type":"uint24" 204 | }, 205 | { 206 | "internalType":"address", 207 | "name":"recipient", 208 | "type":"address" 209 | }, 210 | { 211 | "internalType":"uint256", 212 | "name":"deadline", 213 | "type":"uint256" 214 | }, 215 | { 216 | "internalType":"uint256", 217 | "name":"amountOut", 218 | "type":"uint256" 219 | }, 220 | { 221 | "internalType":"uint256", 222 | "name":"amountInMaximum", 223 | "type":"uint256" 224 | }, 225 | { 226 | "internalType":"uint160", 227 | "name":"sqrtPriceLimitX96", 228 | "type":"uint160" 229 | } 230 | ], 231 | "internalType":"struct ISwapRouter.ExactOutputSingleParams", 232 | "name":"params", 233 | "type":"tuple" 234 | } 235 | ], 236 | "name":"exactOutputSingle", 237 | "outputs":[ 238 | { 239 | "internalType":"uint256", 240 | "name":"amountIn", 241 | "type":"uint256" 242 | } 243 | ], 244 | "stateMutability":"payable", 245 | "type":"function" 246 | }, 247 | { 248 | "inputs":[ 249 | 250 | ], 251 | "name":"factory", 252 | "outputs":[ 253 | { 254 | "internalType":"address", 255 | "name":"", 256 | "type":"address" 257 | } 258 | ], 259 | "stateMutability":"view", 260 | "type":"function" 261 | }, 262 | { 263 | "inputs":[ 264 | { 265 | "internalType":"bytes[]", 266 | "name":"data", 267 | "type":"bytes[]" 268 | } 269 | ], 270 | "name":"multicall", 271 | "outputs":[ 272 | { 273 | "internalType":"bytes[]", 274 | "name":"results", 275 | "type":"bytes[]" 276 | } 277 | ], 278 | "stateMutability":"payable", 279 | "type":"function" 280 | }, 281 | { 282 | "inputs":[ 283 | 284 | ], 285 | "name":"refundETH", 286 | "outputs":[ 287 | 288 | ], 289 | "stateMutability":"payable", 290 | "type":"function" 291 | }, 292 | { 293 | "inputs":[ 294 | { 295 | "internalType":"address", 296 | "name":"token", 297 | "type":"address" 298 | }, 299 | { 300 | "internalType":"uint256", 301 | "name":"value", 302 | "type":"uint256" 303 | }, 304 | { 305 | "internalType":"uint256", 306 | "name":"deadline", 307 | "type":"uint256" 308 | }, 309 | { 310 | "internalType":"uint8", 311 | "name":"v", 312 | "type":"uint8" 313 | }, 314 | { 315 | "internalType":"bytes32", 316 | "name":"r", 317 | "type":"bytes32" 318 | }, 319 | { 320 | "internalType":"bytes32", 321 | "name":"s", 322 | "type":"bytes32" 323 | } 324 | ], 325 | "name":"selfPermit", 326 | "outputs":[ 327 | 328 | ], 329 | "stateMutability":"payable", 330 | "type":"function" 331 | }, 332 | { 333 | "inputs":[ 334 | { 335 | "internalType":"address", 336 | "name":"token", 337 | "type":"address" 338 | }, 339 | { 340 | "internalType":"uint256", 341 | "name":"nonce", 342 | "type":"uint256" 343 | }, 344 | { 345 | "internalType":"uint256", 346 | "name":"expiry", 347 | "type":"uint256" 348 | }, 349 | { 350 | "internalType":"uint8", 351 | "name":"v", 352 | "type":"uint8" 353 | }, 354 | { 355 | "internalType":"bytes32", 356 | "name":"r", 357 | "type":"bytes32" 358 | }, 359 | { 360 | "internalType":"bytes32", 361 | "name":"s", 362 | "type":"bytes32" 363 | } 364 | ], 365 | "name":"selfPermitAllowed", 366 | "outputs":[ 367 | 368 | ], 369 | "stateMutability":"payable", 370 | "type":"function" 371 | }, 372 | { 373 | "inputs":[ 374 | { 375 | "internalType":"address", 376 | "name":"token", 377 | "type":"address" 378 | }, 379 | { 380 | "internalType":"uint256", 381 | "name":"nonce", 382 | "type":"uint256" 383 | }, 384 | { 385 | "internalType":"uint256", 386 | "name":"expiry", 387 | "type":"uint256" 388 | }, 389 | { 390 | "internalType":"uint8", 391 | "name":"v", 392 | "type":"uint8" 393 | }, 394 | { 395 | "internalType":"bytes32", 396 | "name":"r", 397 | "type":"bytes32" 398 | }, 399 | { 400 | "internalType":"bytes32", 401 | "name":"s", 402 | "type":"bytes32" 403 | } 404 | ], 405 | "name":"selfPermitAllowedIfNecessary", 406 | "outputs":[ 407 | 408 | ], 409 | "stateMutability":"payable", 410 | "type":"function" 411 | }, 412 | { 413 | "inputs":[ 414 | { 415 | "internalType":"address", 416 | "name":"token", 417 | "type":"address" 418 | }, 419 | { 420 | "internalType":"uint256", 421 | "name":"value", 422 | "type":"uint256" 423 | }, 424 | { 425 | "internalType":"uint256", 426 | "name":"deadline", 427 | "type":"uint256" 428 | }, 429 | { 430 | "internalType":"uint8", 431 | "name":"v", 432 | "type":"uint8" 433 | }, 434 | { 435 | "internalType":"bytes32", 436 | "name":"r", 437 | "type":"bytes32" 438 | }, 439 | { 440 | "internalType":"bytes32", 441 | "name":"s", 442 | "type":"bytes32" 443 | } 444 | ], 445 | "name":"selfPermitIfNecessary", 446 | "outputs":[ 447 | 448 | ], 449 | "stateMutability":"payable", 450 | "type":"function" 451 | }, 452 | { 453 | "inputs":[ 454 | { 455 | "internalType":"address", 456 | "name":"token", 457 | "type":"address" 458 | }, 459 | { 460 | "internalType":"uint256", 461 | "name":"amountMinimum", 462 | "type":"uint256" 463 | }, 464 | { 465 | "internalType":"address", 466 | "name":"recipient", 467 | "type":"address" 468 | } 469 | ], 470 | "name":"sweepToken", 471 | "outputs":[ 472 | 473 | ], 474 | "stateMutability":"payable", 475 | "type":"function" 476 | }, 477 | { 478 | "inputs":[ 479 | { 480 | "internalType":"address", 481 | "name":"token", 482 | "type":"address" 483 | }, 484 | { 485 | "internalType":"uint256", 486 | "name":"amountMinimum", 487 | "type":"uint256" 488 | }, 489 | { 490 | "internalType":"address", 491 | "name":"recipient", 492 | "type":"address" 493 | }, 494 | { 495 | "internalType":"uint256", 496 | "name":"feeBips", 497 | "type":"uint256" 498 | }, 499 | { 500 | "internalType":"address", 501 | "name":"feeRecipient", 502 | "type":"address" 503 | } 504 | ], 505 | "name":"sweepTokenWithFee", 506 | "outputs":[ 507 | 508 | ], 509 | "stateMutability":"payable", 510 | "type":"function" 511 | }, 512 | { 513 | "inputs":[ 514 | { 515 | "internalType":"int256", 516 | "name":"amount0Delta", 517 | "type":"int256" 518 | }, 519 | { 520 | "internalType":"int256", 521 | "name":"amount1Delta", 522 | "type":"int256" 523 | }, 524 | { 525 | "internalType":"bytes", 526 | "name":"_data", 527 | "type":"bytes" 528 | } 529 | ], 530 | "name":"uniswapV3SwapCallback", 531 | "outputs":[ 532 | 533 | ], 534 | "stateMutability":"nonpayable", 535 | "type":"function" 536 | }, 537 | { 538 | "inputs":[ 539 | { 540 | "internalType":"uint256", 541 | "name":"amountMinimum", 542 | "type":"uint256" 543 | }, 544 | { 545 | "internalType":"address", 546 | "name":"recipient", 547 | "type":"address" 548 | } 549 | ], 550 | "name":"unwrapWETH9", 551 | "outputs":[ 552 | 553 | ], 554 | "stateMutability":"payable", 555 | "type":"function" 556 | }, 557 | { 558 | "inputs":[ 559 | { 560 | "internalType":"uint256", 561 | "name":"amountMinimum", 562 | "type":"uint256" 563 | }, 564 | { 565 | "internalType":"address", 566 | "name":"recipient", 567 | "type":"address" 568 | }, 569 | { 570 | "internalType":"uint256", 571 | "name":"feeBips", 572 | "type":"uint256" 573 | }, 574 | { 575 | "internalType":"address", 576 | "name":"feeRecipient", 577 | "type":"address" 578 | } 579 | ], 580 | "name":"unwrapWETH9WithFee", 581 | "outputs":[ 582 | 583 | ], 584 | "stateMutability":"payable", 585 | "type":"function" 586 | } 587 | ] -------------------------------------------------------------------------------- /src/test/resources/abiFiles/UniswapV3SwapRouter02.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs":[ 4 | { 5 | "internalType":"address", 6 | "name":"_factoryV2", 7 | "type":"address" 8 | }, 9 | { 10 | "internalType":"address", 11 | "name":"factoryV3", 12 | "type":"address" 13 | }, 14 | { 15 | "internalType":"address", 16 | "name":"_positionManager", 17 | "type":"address" 18 | }, 19 | { 20 | "internalType":"address", 21 | "name":"_WETH9", 22 | "type":"address" 23 | } 24 | ], 25 | "stateMutability":"nonpayable", 26 | "type":"constructor" 27 | }, 28 | { 29 | "inputs":[ 30 | 31 | ], 32 | "name":"WETH9", 33 | "outputs":[ 34 | { 35 | "internalType":"address", 36 | "name":"", 37 | "type":"address" 38 | } 39 | ], 40 | "stateMutability":"view", 41 | "type":"function" 42 | }, 43 | { 44 | "inputs":[ 45 | { 46 | "internalType":"address", 47 | "name":"token", 48 | "type":"address" 49 | } 50 | ], 51 | "name":"approveMax", 52 | "outputs":[ 53 | 54 | ], 55 | "stateMutability":"payable", 56 | "type":"function" 57 | }, 58 | { 59 | "inputs":[ 60 | { 61 | "internalType":"address", 62 | "name":"token", 63 | "type":"address" 64 | } 65 | ], 66 | "name":"approveMaxMinusOne", 67 | "outputs":[ 68 | 69 | ], 70 | "stateMutability":"payable", 71 | "type":"function" 72 | }, 73 | { 74 | "inputs":[ 75 | { 76 | "internalType":"address", 77 | "name":"token", 78 | "type":"address" 79 | } 80 | ], 81 | "name":"approveZeroThenMax", 82 | "outputs":[ 83 | 84 | ], 85 | "stateMutability":"payable", 86 | "type":"function" 87 | }, 88 | { 89 | "inputs":[ 90 | { 91 | "internalType":"address", 92 | "name":"token", 93 | "type":"address" 94 | } 95 | ], 96 | "name":"approveZeroThenMaxMinusOne", 97 | "outputs":[ 98 | 99 | ], 100 | "stateMutability":"payable", 101 | "type":"function" 102 | }, 103 | { 104 | "inputs":[ 105 | { 106 | "internalType":"bytes", 107 | "name":"data", 108 | "type":"bytes" 109 | } 110 | ], 111 | "name":"callPositionManager", 112 | "outputs":[ 113 | { 114 | "internalType":"bytes", 115 | "name":"result", 116 | "type":"bytes" 117 | } 118 | ], 119 | "stateMutability":"payable", 120 | "type":"function" 121 | }, 122 | { 123 | "inputs":[ 124 | { 125 | "internalType":"bytes[]", 126 | "name":"paths", 127 | "type":"bytes[]" 128 | }, 129 | { 130 | "internalType":"uint128[]", 131 | "name":"amounts", 132 | "type":"uint128[]" 133 | }, 134 | { 135 | "internalType":"uint24", 136 | "name":"maximumTickDivergence", 137 | "type":"uint24" 138 | }, 139 | { 140 | "internalType":"uint32", 141 | "name":"secondsAgo", 142 | "type":"uint32" 143 | } 144 | ], 145 | "name":"checkOracleSlippage", 146 | "outputs":[ 147 | 148 | ], 149 | "stateMutability":"view", 150 | "type":"function" 151 | }, 152 | { 153 | "inputs":[ 154 | { 155 | "internalType":"bytes", 156 | "name":"path", 157 | "type":"bytes" 158 | }, 159 | { 160 | "internalType":"uint24", 161 | "name":"maximumTickDivergence", 162 | "type":"uint24" 163 | }, 164 | { 165 | "internalType":"uint32", 166 | "name":"secondsAgo", 167 | "type":"uint32" 168 | } 169 | ], 170 | "name":"checkOracleSlippage", 171 | "outputs":[ 172 | 173 | ], 174 | "stateMutability":"view", 175 | "type":"function" 176 | }, 177 | { 178 | "inputs":[ 179 | { 180 | "components":[ 181 | { 182 | "internalType":"bytes", 183 | "name":"path", 184 | "type":"bytes" 185 | }, 186 | { 187 | "internalType":"address", 188 | "name":"recipient", 189 | "type":"address" 190 | }, 191 | { 192 | "internalType":"uint256", 193 | "name":"amountIn", 194 | "type":"uint256" 195 | }, 196 | { 197 | "internalType":"uint256", 198 | "name":"amountOutMinimum", 199 | "type":"uint256" 200 | } 201 | ], 202 | "internalType":"struct IV3SwapRouter.ExactInputParams", 203 | "name":"params", 204 | "type":"tuple" 205 | } 206 | ], 207 | "name":"exactInput", 208 | "outputs":[ 209 | { 210 | "internalType":"uint256", 211 | "name":"amountOut", 212 | "type":"uint256" 213 | } 214 | ], 215 | "stateMutability":"payable", 216 | "type":"function" 217 | }, 218 | { 219 | "inputs":[ 220 | { 221 | "components":[ 222 | { 223 | "internalType":"address", 224 | "name":"tokenIn", 225 | "type":"address" 226 | }, 227 | { 228 | "internalType":"address", 229 | "name":"tokenOut", 230 | "type":"address" 231 | }, 232 | { 233 | "internalType":"uint24", 234 | "name":"fee", 235 | "type":"uint24" 236 | }, 237 | { 238 | "internalType":"address", 239 | "name":"recipient", 240 | "type":"address" 241 | }, 242 | { 243 | "internalType":"uint256", 244 | "name":"amountIn", 245 | "type":"uint256" 246 | }, 247 | { 248 | "internalType":"uint256", 249 | "name":"amountOutMinimum", 250 | "type":"uint256" 251 | }, 252 | { 253 | "internalType":"uint160", 254 | "name":"sqrtPriceLimitX96", 255 | "type":"uint160" 256 | } 257 | ], 258 | "internalType":"struct IV3SwapRouter.ExactInputSingleParams", 259 | "name":"params", 260 | "type":"tuple" 261 | } 262 | ], 263 | "name":"exactInputSingle", 264 | "outputs":[ 265 | { 266 | "internalType":"uint256", 267 | "name":"amountOut", 268 | "type":"uint256" 269 | } 270 | ], 271 | "stateMutability":"payable", 272 | "type":"function" 273 | }, 274 | { 275 | "inputs":[ 276 | { 277 | "components":[ 278 | { 279 | "internalType":"bytes", 280 | "name":"path", 281 | "type":"bytes" 282 | }, 283 | { 284 | "internalType":"address", 285 | "name":"recipient", 286 | "type":"address" 287 | }, 288 | { 289 | "internalType":"uint256", 290 | "name":"amountOut", 291 | "type":"uint256" 292 | }, 293 | { 294 | "internalType":"uint256", 295 | "name":"amountInMaximum", 296 | "type":"uint256" 297 | } 298 | ], 299 | "internalType":"struct IV3SwapRouter.ExactOutputParams", 300 | "name":"params", 301 | "type":"tuple" 302 | } 303 | ], 304 | "name":"exactOutput", 305 | "outputs":[ 306 | { 307 | "internalType":"uint256", 308 | "name":"amountIn", 309 | "type":"uint256" 310 | } 311 | ], 312 | "stateMutability":"payable", 313 | "type":"function" 314 | }, 315 | { 316 | "inputs":[ 317 | { 318 | "components":[ 319 | { 320 | "internalType":"address", 321 | "name":"tokenIn", 322 | "type":"address" 323 | }, 324 | { 325 | "internalType":"address", 326 | "name":"tokenOut", 327 | "type":"address" 328 | }, 329 | { 330 | "internalType":"uint24", 331 | "name":"fee", 332 | "type":"uint24" 333 | }, 334 | { 335 | "internalType":"address", 336 | "name":"recipient", 337 | "type":"address" 338 | }, 339 | { 340 | "internalType":"uint256", 341 | "name":"amountOut", 342 | "type":"uint256" 343 | }, 344 | { 345 | "internalType":"uint256", 346 | "name":"amountInMaximum", 347 | "type":"uint256" 348 | }, 349 | { 350 | "internalType":"uint160", 351 | "name":"sqrtPriceLimitX96", 352 | "type":"uint160" 353 | } 354 | ], 355 | "internalType":"struct IV3SwapRouter.ExactOutputSingleParams", 356 | "name":"params", 357 | "type":"tuple" 358 | } 359 | ], 360 | "name":"exactOutputSingle", 361 | "outputs":[ 362 | { 363 | "internalType":"uint256", 364 | "name":"amountIn", 365 | "type":"uint256" 366 | } 367 | ], 368 | "stateMutability":"payable", 369 | "type":"function" 370 | }, 371 | { 372 | "inputs":[ 373 | 374 | ], 375 | "name":"factory", 376 | "outputs":[ 377 | { 378 | "internalType":"address", 379 | "name":"", 380 | "type":"address" 381 | } 382 | ], 383 | "stateMutability":"view", 384 | "type":"function" 385 | }, 386 | { 387 | "inputs":[ 388 | 389 | ], 390 | "name":"factoryV2", 391 | "outputs":[ 392 | { 393 | "internalType":"address", 394 | "name":"", 395 | "type":"address" 396 | } 397 | ], 398 | "stateMutability":"view", 399 | "type":"function" 400 | }, 401 | { 402 | "inputs":[ 403 | { 404 | "internalType":"address", 405 | "name":"token", 406 | "type":"address" 407 | }, 408 | { 409 | "internalType":"uint256", 410 | "name":"amount", 411 | "type":"uint256" 412 | } 413 | ], 414 | "name":"getApprovalType", 415 | "outputs":[ 416 | { 417 | "internalType":"enum IApproveAndCall.ApprovalType", 418 | "name":"", 419 | "type":"uint8" 420 | } 421 | ], 422 | "stateMutability":"nonpayable", 423 | "type":"function" 424 | }, 425 | { 426 | "inputs":[ 427 | { 428 | "components":[ 429 | { 430 | "internalType":"address", 431 | "name":"token0", 432 | "type":"address" 433 | }, 434 | { 435 | "internalType":"address", 436 | "name":"token1", 437 | "type":"address" 438 | }, 439 | { 440 | "internalType":"uint256", 441 | "name":"tokenId", 442 | "type":"uint256" 443 | }, 444 | { 445 | "internalType":"uint256", 446 | "name":"amount0Min", 447 | "type":"uint256" 448 | }, 449 | { 450 | "internalType":"uint256", 451 | "name":"amount1Min", 452 | "type":"uint256" 453 | } 454 | ], 455 | "internalType":"struct IApproveAndCall.IncreaseLiquidityParams", 456 | "name":"params", 457 | "type":"tuple" 458 | } 459 | ], 460 | "name":"increaseLiquidity", 461 | "outputs":[ 462 | { 463 | "internalType":"bytes", 464 | "name":"result", 465 | "type":"bytes" 466 | } 467 | ], 468 | "stateMutability":"payable", 469 | "type":"function" 470 | }, 471 | { 472 | "inputs":[ 473 | { 474 | "components":[ 475 | { 476 | "internalType":"address", 477 | "name":"token0", 478 | "type":"address" 479 | }, 480 | { 481 | "internalType":"address", 482 | "name":"token1", 483 | "type":"address" 484 | }, 485 | { 486 | "internalType":"uint24", 487 | "name":"fee", 488 | "type":"uint24" 489 | }, 490 | { 491 | "internalType":"int24", 492 | "name":"tickLower", 493 | "type":"int24" 494 | }, 495 | { 496 | "internalType":"int24", 497 | "name":"tickUpper", 498 | "type":"int24" 499 | }, 500 | { 501 | "internalType":"uint256", 502 | "name":"amount0Min", 503 | "type":"uint256" 504 | }, 505 | { 506 | "internalType":"uint256", 507 | "name":"amount1Min", 508 | "type":"uint256" 509 | }, 510 | { 511 | "internalType":"address", 512 | "name":"recipient", 513 | "type":"address" 514 | } 515 | ], 516 | "internalType":"struct IApproveAndCall.MintParams", 517 | "name":"params", 518 | "type":"tuple" 519 | } 520 | ], 521 | "name":"mint", 522 | "outputs":[ 523 | { 524 | "internalType":"bytes", 525 | "name":"result", 526 | "type":"bytes" 527 | } 528 | ], 529 | "stateMutability":"payable", 530 | "type":"function" 531 | }, 532 | { 533 | "inputs":[ 534 | { 535 | "internalType":"bytes32", 536 | "name":"previousBlockhash", 537 | "type":"bytes32" 538 | }, 539 | { 540 | "internalType":"bytes[]", 541 | "name":"data", 542 | "type":"bytes[]" 543 | } 544 | ], 545 | "name":"multicall", 546 | "outputs":[ 547 | { 548 | "internalType":"bytes[]", 549 | "name":"", 550 | "type":"bytes[]" 551 | } 552 | ], 553 | "stateMutability":"payable", 554 | "type":"function" 555 | }, 556 | { 557 | "inputs":[ 558 | { 559 | "internalType":"uint256", 560 | "name":"deadline", 561 | "type":"uint256" 562 | }, 563 | { 564 | "internalType":"bytes[]", 565 | "name":"data", 566 | "type":"bytes[]" 567 | } 568 | ], 569 | "name":"multicall", 570 | "outputs":[ 571 | { 572 | "internalType":"bytes[]", 573 | "name":"", 574 | "type":"bytes[]" 575 | } 576 | ], 577 | "stateMutability":"payable", 578 | "type":"function" 579 | }, 580 | { 581 | "inputs":[ 582 | { 583 | "internalType":"bytes[]", 584 | "name":"data", 585 | "type":"bytes[]" 586 | } 587 | ], 588 | "name":"multicall", 589 | "outputs":[ 590 | { 591 | "internalType":"bytes[]", 592 | "name":"results", 593 | "type":"bytes[]" 594 | } 595 | ], 596 | "stateMutability":"payable", 597 | "type":"function" 598 | }, 599 | { 600 | "inputs":[ 601 | 602 | ], 603 | "name":"positionManager", 604 | "outputs":[ 605 | { 606 | "internalType":"address", 607 | "name":"", 608 | "type":"address" 609 | } 610 | ], 611 | "stateMutability":"view", 612 | "type":"function" 613 | }, 614 | { 615 | "inputs":[ 616 | { 617 | "internalType":"address", 618 | "name":"token", 619 | "type":"address" 620 | }, 621 | { 622 | "internalType":"uint256", 623 | "name":"value", 624 | "type":"uint256" 625 | } 626 | ], 627 | "name":"pull", 628 | "outputs":[ 629 | 630 | ], 631 | "stateMutability":"payable", 632 | "type":"function" 633 | }, 634 | { 635 | "inputs":[ 636 | 637 | ], 638 | "name":"refundETH", 639 | "outputs":[ 640 | 641 | ], 642 | "stateMutability":"payable", 643 | "type":"function" 644 | }, 645 | { 646 | "inputs":[ 647 | { 648 | "internalType":"address", 649 | "name":"token", 650 | "type":"address" 651 | }, 652 | { 653 | "internalType":"uint256", 654 | "name":"value", 655 | "type":"uint256" 656 | }, 657 | { 658 | "internalType":"uint256", 659 | "name":"deadline", 660 | "type":"uint256" 661 | }, 662 | { 663 | "internalType":"uint8", 664 | "name":"v", 665 | "type":"uint8" 666 | }, 667 | { 668 | "internalType":"bytes32", 669 | "name":"r", 670 | "type":"bytes32" 671 | }, 672 | { 673 | "internalType":"bytes32", 674 | "name":"s", 675 | "type":"bytes32" 676 | } 677 | ], 678 | "name":"selfPermit", 679 | "outputs":[ 680 | 681 | ], 682 | "stateMutability":"payable", 683 | "type":"function" 684 | }, 685 | { 686 | "inputs":[ 687 | { 688 | "internalType":"address", 689 | "name":"token", 690 | "type":"address" 691 | }, 692 | { 693 | "internalType":"uint256", 694 | "name":"nonce", 695 | "type":"uint256" 696 | }, 697 | { 698 | "internalType":"uint256", 699 | "name":"expiry", 700 | "type":"uint256" 701 | }, 702 | { 703 | "internalType":"uint8", 704 | "name":"v", 705 | "type":"uint8" 706 | }, 707 | { 708 | "internalType":"bytes32", 709 | "name":"r", 710 | "type":"bytes32" 711 | }, 712 | { 713 | "internalType":"bytes32", 714 | "name":"s", 715 | "type":"bytes32" 716 | } 717 | ], 718 | "name":"selfPermitAllowed", 719 | "outputs":[ 720 | 721 | ], 722 | "stateMutability":"payable", 723 | "type":"function" 724 | }, 725 | { 726 | "inputs":[ 727 | { 728 | "internalType":"address", 729 | "name":"token", 730 | "type":"address" 731 | }, 732 | { 733 | "internalType":"uint256", 734 | "name":"nonce", 735 | "type":"uint256" 736 | }, 737 | { 738 | "internalType":"uint256", 739 | "name":"expiry", 740 | "type":"uint256" 741 | }, 742 | { 743 | "internalType":"uint8", 744 | "name":"v", 745 | "type":"uint8" 746 | }, 747 | { 748 | "internalType":"bytes32", 749 | "name":"r", 750 | "type":"bytes32" 751 | }, 752 | { 753 | "internalType":"bytes32", 754 | "name":"s", 755 | "type":"bytes32" 756 | } 757 | ], 758 | "name":"selfPermitAllowedIfNecessary", 759 | "outputs":[ 760 | 761 | ], 762 | "stateMutability":"payable", 763 | "type":"function" 764 | }, 765 | { 766 | "inputs":[ 767 | { 768 | "internalType":"address", 769 | "name":"token", 770 | "type":"address" 771 | }, 772 | { 773 | "internalType":"uint256", 774 | "name":"value", 775 | "type":"uint256" 776 | }, 777 | { 778 | "internalType":"uint256", 779 | "name":"deadline", 780 | "type":"uint256" 781 | }, 782 | { 783 | "internalType":"uint8", 784 | "name":"v", 785 | "type":"uint8" 786 | }, 787 | { 788 | "internalType":"bytes32", 789 | "name":"r", 790 | "type":"bytes32" 791 | }, 792 | { 793 | "internalType":"bytes32", 794 | "name":"s", 795 | "type":"bytes32" 796 | } 797 | ], 798 | "name":"selfPermitIfNecessary", 799 | "outputs":[ 800 | 801 | ], 802 | "stateMutability":"payable", 803 | "type":"function" 804 | }, 805 | { 806 | "inputs":[ 807 | { 808 | "internalType":"uint256", 809 | "name":"amountIn", 810 | "type":"uint256" 811 | }, 812 | { 813 | "internalType":"uint256", 814 | "name":"amountOutMin", 815 | "type":"uint256" 816 | }, 817 | { 818 | "internalType":"address[]", 819 | "name":"path", 820 | "type":"address[]" 821 | }, 822 | { 823 | "internalType":"address", 824 | "name":"to", 825 | "type":"address" 826 | } 827 | ], 828 | "name":"swapExactTokensForTokens", 829 | "outputs":[ 830 | { 831 | "internalType":"uint256", 832 | "name":"amountOut", 833 | "type":"uint256" 834 | } 835 | ], 836 | "stateMutability":"payable", 837 | "type":"function" 838 | }, 839 | { 840 | "inputs":[ 841 | { 842 | "internalType":"uint256", 843 | "name":"amountOut", 844 | "type":"uint256" 845 | }, 846 | { 847 | "internalType":"uint256", 848 | "name":"amountInMax", 849 | "type":"uint256" 850 | }, 851 | { 852 | "internalType":"address[]", 853 | "name":"path", 854 | "type":"address[]" 855 | }, 856 | { 857 | "internalType":"address", 858 | "name":"to", 859 | "type":"address" 860 | } 861 | ], 862 | "name":"swapTokensForExactTokens", 863 | "outputs":[ 864 | { 865 | "internalType":"uint256", 866 | "name":"amountIn", 867 | "type":"uint256" 868 | } 869 | ], 870 | "stateMutability":"payable", 871 | "type":"function" 872 | }, 873 | { 874 | "inputs":[ 875 | { 876 | "internalType":"address", 877 | "name":"token", 878 | "type":"address" 879 | }, 880 | { 881 | "internalType":"uint256", 882 | "name":"amountMinimum", 883 | "type":"uint256" 884 | }, 885 | { 886 | "internalType":"address", 887 | "name":"recipient", 888 | "type":"address" 889 | } 890 | ], 891 | "name":"sweepToken", 892 | "outputs":[ 893 | 894 | ], 895 | "stateMutability":"payable", 896 | "type":"function" 897 | }, 898 | { 899 | "inputs":[ 900 | { 901 | "internalType":"address", 902 | "name":"token", 903 | "type":"address" 904 | }, 905 | { 906 | "internalType":"uint256", 907 | "name":"amountMinimum", 908 | "type":"uint256" 909 | } 910 | ], 911 | "name":"sweepToken", 912 | "outputs":[ 913 | 914 | ], 915 | "stateMutability":"payable", 916 | "type":"function" 917 | }, 918 | { 919 | "inputs":[ 920 | { 921 | "internalType":"address", 922 | "name":"token", 923 | "type":"address" 924 | }, 925 | { 926 | "internalType":"uint256", 927 | "name":"amountMinimum", 928 | "type":"uint256" 929 | }, 930 | { 931 | "internalType":"uint256", 932 | "name":"feeBips", 933 | "type":"uint256" 934 | }, 935 | { 936 | "internalType":"address", 937 | "name":"feeRecipient", 938 | "type":"address" 939 | } 940 | ], 941 | "name":"sweepTokenWithFee", 942 | "outputs":[ 943 | 944 | ], 945 | "stateMutability":"payable", 946 | "type":"function" 947 | }, 948 | { 949 | "inputs":[ 950 | { 951 | "internalType":"address", 952 | "name":"token", 953 | "type":"address" 954 | }, 955 | { 956 | "internalType":"uint256", 957 | "name":"amountMinimum", 958 | "type":"uint256" 959 | }, 960 | { 961 | "internalType":"address", 962 | "name":"recipient", 963 | "type":"address" 964 | }, 965 | { 966 | "internalType":"uint256", 967 | "name":"feeBips", 968 | "type":"uint256" 969 | }, 970 | { 971 | "internalType":"address", 972 | "name":"feeRecipient", 973 | "type":"address" 974 | } 975 | ], 976 | "name":"sweepTokenWithFee", 977 | "outputs":[ 978 | 979 | ], 980 | "stateMutability":"payable", 981 | "type":"function" 982 | }, 983 | { 984 | "inputs":[ 985 | { 986 | "internalType":"int256", 987 | "name":"amount0Delta", 988 | "type":"int256" 989 | }, 990 | { 991 | "internalType":"int256", 992 | "name":"amount1Delta", 993 | "type":"int256" 994 | }, 995 | { 996 | "internalType":"bytes", 997 | "name":"_data", 998 | "type":"bytes" 999 | } 1000 | ], 1001 | "name":"uniswapV3SwapCallback", 1002 | "outputs":[ 1003 | 1004 | ], 1005 | "stateMutability":"nonpayable", 1006 | "type":"function" 1007 | }, 1008 | { 1009 | "inputs":[ 1010 | { 1011 | "internalType":"uint256", 1012 | "name":"amountMinimum", 1013 | "type":"uint256" 1014 | }, 1015 | { 1016 | "internalType":"address", 1017 | "name":"recipient", 1018 | "type":"address" 1019 | } 1020 | ], 1021 | "name":"unwrapWETH9", 1022 | "outputs":[ 1023 | 1024 | ], 1025 | "stateMutability":"payable", 1026 | "type":"function" 1027 | }, 1028 | { 1029 | "inputs":[ 1030 | { 1031 | "internalType":"uint256", 1032 | "name":"amountMinimum", 1033 | "type":"uint256" 1034 | } 1035 | ], 1036 | "name":"unwrapWETH9", 1037 | "outputs":[ 1038 | 1039 | ], 1040 | "stateMutability":"payable", 1041 | "type":"function" 1042 | }, 1043 | { 1044 | "inputs":[ 1045 | { 1046 | "internalType":"uint256", 1047 | "name":"amountMinimum", 1048 | "type":"uint256" 1049 | }, 1050 | { 1051 | "internalType":"address", 1052 | "name":"recipient", 1053 | "type":"address" 1054 | }, 1055 | { 1056 | "internalType":"uint256", 1057 | "name":"feeBips", 1058 | "type":"uint256" 1059 | }, 1060 | { 1061 | "internalType":"address", 1062 | "name":"feeRecipient", 1063 | "type":"address" 1064 | } 1065 | ], 1066 | "name":"unwrapWETH9WithFee", 1067 | "outputs":[ 1068 | 1069 | ], 1070 | "stateMutability":"payable", 1071 | "type":"function" 1072 | }, 1073 | { 1074 | "inputs":[ 1075 | { 1076 | "internalType":"uint256", 1077 | "name":"amountMinimum", 1078 | "type":"uint256" 1079 | }, 1080 | { 1081 | "internalType":"uint256", 1082 | "name":"feeBips", 1083 | "type":"uint256" 1084 | }, 1085 | { 1086 | "internalType":"address", 1087 | "name":"feeRecipient", 1088 | "type":"address" 1089 | } 1090 | ], 1091 | "name":"unwrapWETH9WithFee", 1092 | "outputs":[ 1093 | 1094 | ], 1095 | "stateMutability":"payable", 1096 | "type":"function" 1097 | }, 1098 | { 1099 | "inputs":[ 1100 | { 1101 | "internalType":"uint256", 1102 | "name":"value", 1103 | "type":"uint256" 1104 | } 1105 | ], 1106 | "name":"wrapETH", 1107 | "outputs":[ 1108 | 1109 | ], 1110 | "stateMutability":"payable", 1111 | "type":"function" 1112 | } 1113 | ] -------------------------------------------------------------------------------- /src/test/resources/abiFiles/ZkSync.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "inputs":[ 4 | 5 | ], 6 | "stateMutability":"nonpayable", 7 | "type":"constructor" 8 | }, 9 | { 10 | "anonymous":false, 11 | "inputs":[ 12 | { 13 | "indexed":true, 14 | "internalType":"address", 15 | "name":"addr", 16 | "type":"address" 17 | } 18 | ], 19 | "name":"ApproveCutUpgradeNoticePeriod", 20 | "type":"event" 21 | }, 22 | { 23 | "anonymous":false, 24 | "inputs":[ 25 | { 26 | "indexed":true, 27 | "internalType":"uint32", 28 | "name":"blockNumber", 29 | "type":"uint32" 30 | } 31 | ], 32 | "name":"BlockCommit", 33 | "type":"event" 34 | }, 35 | { 36 | "anonymous":false, 37 | "inputs":[ 38 | { 39 | "indexed":true, 40 | "internalType":"uint32", 41 | "name":"blockNumber", 42 | "type":"uint32" 43 | } 44 | ], 45 | "name":"BlockVerification", 46 | "type":"event" 47 | }, 48 | { 49 | "anonymous":false, 50 | "inputs":[ 51 | { 52 | "indexed":false, 53 | "internalType":"uint32", 54 | "name":"totalBlocksVerified", 55 | "type":"uint32" 56 | }, 57 | { 58 | "indexed":false, 59 | "internalType":"uint32", 60 | "name":"totalBlocksCommitted", 61 | "type":"uint32" 62 | } 63 | ], 64 | "name":"BlocksRevert", 65 | "type":"event" 66 | }, 67 | { 68 | "anonymous":false, 69 | "inputs":[ 70 | { 71 | "indexed":true, 72 | "internalType":"uint16", 73 | "name":"tokenId", 74 | "type":"uint16" 75 | }, 76 | { 77 | "indexed":false, 78 | "internalType":"uint128", 79 | "name":"amount", 80 | "type":"uint128" 81 | } 82 | ], 83 | "name":"Deposit", 84 | "type":"event" 85 | }, 86 | { 87 | "anonymous":false, 88 | "inputs":[ 89 | { 90 | "indexed":true, 91 | "internalType":"uint32", 92 | "name":"zkSyncBlockId", 93 | "type":"uint32" 94 | }, 95 | { 96 | "indexed":true, 97 | "internalType":"uint32", 98 | "name":"accountId", 99 | "type":"uint32" 100 | }, 101 | { 102 | "indexed":false, 103 | "internalType":"address", 104 | "name":"owner", 105 | "type":"address" 106 | }, 107 | { 108 | "indexed":true, 109 | "internalType":"uint16", 110 | "name":"tokenId", 111 | "type":"uint16" 112 | }, 113 | { 114 | "indexed":false, 115 | "internalType":"uint128", 116 | "name":"amount", 117 | "type":"uint128" 118 | } 119 | ], 120 | "name":"DepositCommit", 121 | "type":"event" 122 | }, 123 | { 124 | "anonymous":false, 125 | "inputs":[ 126 | 127 | ], 128 | "name":"ExodusMode", 129 | "type":"event" 130 | }, 131 | { 132 | "anonymous":false, 133 | "inputs":[ 134 | { 135 | "indexed":true, 136 | "internalType":"address", 137 | "name":"sender", 138 | "type":"address" 139 | }, 140 | { 141 | "indexed":false, 142 | "internalType":"uint32", 143 | "name":"nonce", 144 | "type":"uint32" 145 | }, 146 | { 147 | "indexed":false, 148 | "internalType":"bytes", 149 | "name":"fact", 150 | "type":"bytes" 151 | } 152 | ], 153 | "name":"FactAuth", 154 | "type":"event" 155 | }, 156 | { 157 | "anonymous":false, 158 | "inputs":[ 159 | { 160 | "indexed":true, 161 | "internalType":"uint32", 162 | "name":"zkSyncBlockId", 163 | "type":"uint32" 164 | }, 165 | { 166 | "indexed":true, 167 | "internalType":"uint32", 168 | "name":"accountId", 169 | "type":"uint32" 170 | }, 171 | { 172 | "indexed":false, 173 | "internalType":"address", 174 | "name":"owner", 175 | "type":"address" 176 | }, 177 | { 178 | "indexed":true, 179 | "internalType":"uint16", 180 | "name":"tokenId", 181 | "type":"uint16" 182 | }, 183 | { 184 | "indexed":false, 185 | "internalType":"uint128", 186 | "name":"amount", 187 | "type":"uint128" 188 | } 189 | ], 190 | "name":"FullExitCommit", 191 | "type":"event" 192 | }, 193 | { 194 | "anonymous":false, 195 | "inputs":[ 196 | { 197 | "indexed":false, 198 | "internalType":"address", 199 | "name":"sender", 200 | "type":"address" 201 | }, 202 | { 203 | "indexed":false, 204 | "internalType":"uint64", 205 | "name":"serialId", 206 | "type":"uint64" 207 | }, 208 | { 209 | "indexed":false, 210 | "internalType":"enum Operations.OpType", 211 | "name":"opType", 212 | "type":"uint8" 213 | }, 214 | { 215 | "indexed":false, 216 | "internalType":"bytes", 217 | "name":"pubData", 218 | "type":"bytes" 219 | }, 220 | { 221 | "indexed":false, 222 | "internalType":"uint256", 223 | "name":"expirationBlock", 224 | "type":"uint256" 225 | } 226 | ], 227 | "name":"NewPriorityRequest", 228 | "type":"event" 229 | }, 230 | { 231 | "anonymous":false, 232 | "inputs":[ 233 | { 234 | "indexed":false, 235 | "internalType":"uint256", 236 | "name":"newNoticePeriod", 237 | "type":"uint256" 238 | } 239 | ], 240 | "name":"NoticePeriodChange", 241 | "type":"event" 242 | }, 243 | { 244 | "anonymous":false, 245 | "inputs":[ 246 | { 247 | "indexed":true, 248 | "internalType":"address", 249 | "name":"owner", 250 | "type":"address" 251 | }, 252 | { 253 | "indexed":true, 254 | "internalType":"uint16", 255 | "name":"tokenId", 256 | "type":"uint16" 257 | }, 258 | { 259 | "indexed":false, 260 | "internalType":"uint128", 261 | "name":"amount", 262 | "type":"uint128" 263 | } 264 | ], 265 | "name":"Withdrawal", 266 | "type":"event" 267 | }, 268 | { 269 | "anonymous":false, 270 | "inputs":[ 271 | { 272 | "indexed":true, 273 | "internalType":"uint32", 274 | "name":"tokenId", 275 | "type":"uint32" 276 | } 277 | ], 278 | "name":"WithdrawalNFT", 279 | "type":"event" 280 | }, 281 | { 282 | "anonymous":false, 283 | "inputs":[ 284 | { 285 | "indexed":true, 286 | "internalType":"uint32", 287 | "name":"tokenId", 288 | "type":"uint32" 289 | } 290 | ], 291 | "name":"WithdrawalNFTPending", 292 | "type":"event" 293 | }, 294 | { 295 | "anonymous":false, 296 | "inputs":[ 297 | { 298 | "indexed":true, 299 | "internalType":"uint16", 300 | "name":"tokenId", 301 | "type":"uint16" 302 | }, 303 | { 304 | "indexed":true, 305 | "internalType":"address", 306 | "name":"recipient", 307 | "type":"address" 308 | }, 309 | { 310 | "indexed":false, 311 | "internalType":"uint128", 312 | "name":"amount", 313 | "type":"uint128" 314 | }, 315 | { 316 | "indexed":false, 317 | "internalType":"enum Operations.WithdrawalType", 318 | "name":"withdrawalType", 319 | "type":"uint8" 320 | } 321 | ], 322 | "name":"WithdrawalPending", 323 | "type":"event" 324 | }, 325 | { 326 | "inputs":[ 327 | 328 | ], 329 | "name":"activateExodusMode", 330 | "outputs":[ 331 | { 332 | "internalType":"bool", 333 | "name":"", 334 | "type":"bool" 335 | } 336 | ], 337 | "stateMutability":"nonpayable", 338 | "type":"function" 339 | }, 340 | { 341 | "inputs":[ 342 | { 343 | "internalType":"address", 344 | "name":"", 345 | "type":"address" 346 | }, 347 | { 348 | "internalType":"uint32", 349 | "name":"", 350 | "type":"uint32" 351 | } 352 | ], 353 | "name":"authFacts", 354 | "outputs":[ 355 | { 356 | "internalType":"bytes32", 357 | "name":"", 358 | "type":"bytes32" 359 | } 360 | ], 361 | "stateMutability":"view", 362 | "type":"function" 363 | }, 364 | { 365 | "inputs":[ 366 | { 367 | "internalType":"address", 368 | "name":"", 369 | "type":"address" 370 | }, 371 | { 372 | "internalType":"uint32", 373 | "name":"", 374 | "type":"uint32" 375 | } 376 | ], 377 | "name":"authFactsResetTimer", 378 | "outputs":[ 379 | { 380 | "internalType":"uint256", 381 | "name":"", 382 | "type":"uint256" 383 | } 384 | ], 385 | "stateMutability":"view", 386 | "type":"function" 387 | }, 388 | { 389 | "inputs":[ 390 | { 391 | "internalType":"uint64", 392 | "name":"_n", 393 | "type":"uint64" 394 | }, 395 | { 396 | "internalType":"bytes[]", 397 | "name":"_depositsPubdata", 398 | "type":"bytes[]" 399 | } 400 | ], 401 | "name":"cancelOutstandingDepositsForExodusMode", 402 | "outputs":[ 403 | 404 | ], 405 | "stateMutability":"nonpayable", 406 | "type":"function" 407 | }, 408 | { 409 | "inputs":[ 410 | { 411 | "components":[ 412 | { 413 | "internalType":"uint32", 414 | "name":"blockNumber", 415 | "type":"uint32" 416 | }, 417 | { 418 | "internalType":"uint64", 419 | "name":"priorityOperations", 420 | "type":"uint64" 421 | }, 422 | { 423 | "internalType":"bytes32", 424 | "name":"pendingOnchainOperationsHash", 425 | "type":"bytes32" 426 | }, 427 | { 428 | "internalType":"uint256", 429 | "name":"timestamp", 430 | "type":"uint256" 431 | }, 432 | { 433 | "internalType":"bytes32", 434 | "name":"stateHash", 435 | "type":"bytes32" 436 | }, 437 | { 438 | "internalType":"bytes32", 439 | "name":"commitment", 440 | "type":"bytes32" 441 | } 442 | ], 443 | "internalType":"struct Storage.StoredBlockInfo", 444 | "name":"_lastCommittedBlockData", 445 | "type":"tuple" 446 | }, 447 | { 448 | "components":[ 449 | { 450 | "internalType":"bytes32", 451 | "name":"newStateHash", 452 | "type":"bytes32" 453 | }, 454 | { 455 | "internalType":"bytes", 456 | "name":"publicData", 457 | "type":"bytes" 458 | }, 459 | { 460 | "internalType":"uint256", 461 | "name":"timestamp", 462 | "type":"uint256" 463 | }, 464 | { 465 | "components":[ 466 | { 467 | "internalType":"bytes", 468 | "name":"ethWitness", 469 | "type":"bytes" 470 | }, 471 | { 472 | "internalType":"uint32", 473 | "name":"publicDataOffset", 474 | "type":"uint32" 475 | } 476 | ], 477 | "internalType":"struct ZkSync.OnchainOperationData[]", 478 | "name":"onchainOperations", 479 | "type":"tuple[]" 480 | }, 481 | { 482 | "internalType":"uint32", 483 | "name":"blockNumber", 484 | "type":"uint32" 485 | }, 486 | { 487 | "internalType":"uint32", 488 | "name":"feeAccount", 489 | "type":"uint32" 490 | } 491 | ], 492 | "internalType":"struct ZkSync.CommitBlockInfo[]", 493 | "name":"_newBlocksData", 494 | "type":"tuple[]" 495 | } 496 | ], 497 | "name":"commitBlocks", 498 | "outputs":[ 499 | 500 | ], 501 | "stateMutability":"nonpayable", 502 | "type":"function" 503 | }, 504 | { 505 | "inputs":[ 506 | { 507 | "internalType":"bytes32", 508 | "name":"targetsHash", 509 | "type":"bytes32" 510 | } 511 | ], 512 | "name":"cutUpgradeNoticePeriod", 513 | "outputs":[ 514 | 515 | ], 516 | "stateMutability":"nonpayable", 517 | "type":"function" 518 | }, 519 | { 520 | "inputs":[ 521 | { 522 | "internalType":"bytes[]", 523 | "name":"signatures", 524 | "type":"bytes[]" 525 | } 526 | ], 527 | "name":"cutUpgradeNoticePeriodBySignature", 528 | "outputs":[ 529 | 530 | ], 531 | "stateMutability":"nonpayable", 532 | "type":"function" 533 | }, 534 | { 535 | "inputs":[ 536 | { 537 | "internalType":"contract IERC20", 538 | "name":"_token", 539 | "type":"address" 540 | }, 541 | { 542 | "internalType":"uint104", 543 | "name":"_amount", 544 | "type":"uint104" 545 | }, 546 | { 547 | "internalType":"address", 548 | "name":"_zkSyncAddress", 549 | "type":"address" 550 | } 551 | ], 552 | "name":"depositERC20", 553 | "outputs":[ 554 | 555 | ], 556 | "stateMutability":"nonpayable", 557 | "type":"function" 558 | }, 559 | { 560 | "inputs":[ 561 | { 562 | "internalType":"address", 563 | "name":"_zkSyncAddress", 564 | "type":"address" 565 | } 566 | ], 567 | "name":"depositETH", 568 | "outputs":[ 569 | 570 | ], 571 | "stateMutability":"payable", 572 | "type":"function" 573 | }, 574 | { 575 | "inputs":[ 576 | { 577 | "components":[ 578 | { 579 | "components":[ 580 | { 581 | "internalType":"uint32", 582 | "name":"blockNumber", 583 | "type":"uint32" 584 | }, 585 | { 586 | "internalType":"uint64", 587 | "name":"priorityOperations", 588 | "type":"uint64" 589 | }, 590 | { 591 | "internalType":"bytes32", 592 | "name":"pendingOnchainOperationsHash", 593 | "type":"bytes32" 594 | }, 595 | { 596 | "internalType":"uint256", 597 | "name":"timestamp", 598 | "type":"uint256" 599 | }, 600 | { 601 | "internalType":"bytes32", 602 | "name":"stateHash", 603 | "type":"bytes32" 604 | }, 605 | { 606 | "internalType":"bytes32", 607 | "name":"commitment", 608 | "type":"bytes32" 609 | } 610 | ], 611 | "internalType":"struct Storage.StoredBlockInfo", 612 | "name":"storedBlock", 613 | "type":"tuple" 614 | }, 615 | { 616 | "internalType":"bytes[]", 617 | "name":"pendingOnchainOpsPubdata", 618 | "type":"bytes[]" 619 | } 620 | ], 621 | "internalType":"struct ZkSync.ExecuteBlockInfo[]", 622 | "name":"_blocksData", 623 | "type":"tuple[]" 624 | } 625 | ], 626 | "name":"executeBlocks", 627 | "outputs":[ 628 | 629 | ], 630 | "stateMutability":"nonpayable", 631 | "type":"function" 632 | }, 633 | { 634 | "inputs":[ 635 | 636 | ], 637 | "name":"exodusMode", 638 | "outputs":[ 639 | { 640 | "internalType":"bool", 641 | "name":"", 642 | "type":"bool" 643 | } 644 | ], 645 | "stateMutability":"view", 646 | "type":"function" 647 | }, 648 | { 649 | "inputs":[ 650 | 651 | ], 652 | "name":"firstPriorityRequestId", 653 | "outputs":[ 654 | { 655 | "internalType":"uint64", 656 | "name":"", 657 | "type":"uint64" 658 | } 659 | ], 660 | "stateMutability":"view", 661 | "type":"function" 662 | }, 663 | { 664 | "inputs":[ 665 | 666 | ], 667 | "name":"getNoticePeriod", 668 | "outputs":[ 669 | { 670 | "internalType":"uint256", 671 | "name":"", 672 | "type":"uint256" 673 | } 674 | ], 675 | "stateMutability":"pure", 676 | "type":"function" 677 | }, 678 | { 679 | "inputs":[ 680 | { 681 | "internalType":"address", 682 | "name":"_address", 683 | "type":"address" 684 | }, 685 | { 686 | "internalType":"address", 687 | "name":"_token", 688 | "type":"address" 689 | } 690 | ], 691 | "name":"getPendingBalance", 692 | "outputs":[ 693 | { 694 | "internalType":"uint128", 695 | "name":"", 696 | "type":"uint128" 697 | } 698 | ], 699 | "stateMutability":"view", 700 | "type":"function" 701 | }, 702 | { 703 | "inputs":[ 704 | { 705 | "internalType":"bytes", 706 | "name":"initializationParameters", 707 | "type":"bytes" 708 | } 709 | ], 710 | "name":"initialize", 711 | "outputs":[ 712 | 713 | ], 714 | "stateMutability":"nonpayable", 715 | "type":"function" 716 | }, 717 | { 718 | "inputs":[ 719 | 720 | ], 721 | "name":"isReadyForUpgrade", 722 | "outputs":[ 723 | { 724 | "internalType":"bool", 725 | "name":"", 726 | "type":"bool" 727 | } 728 | ], 729 | "stateMutability":"pure", 730 | "type":"function" 731 | }, 732 | { 733 | "inputs":[ 734 | { 735 | "components":[ 736 | { 737 | "internalType":"uint32", 738 | "name":"blockNumber", 739 | "type":"uint32" 740 | }, 741 | { 742 | "internalType":"uint64", 743 | "name":"priorityOperations", 744 | "type":"uint64" 745 | }, 746 | { 747 | "internalType":"bytes32", 748 | "name":"pendingOnchainOperationsHash", 749 | "type":"bytes32" 750 | }, 751 | { 752 | "internalType":"uint256", 753 | "name":"timestamp", 754 | "type":"uint256" 755 | }, 756 | { 757 | "internalType":"bytes32", 758 | "name":"stateHash", 759 | "type":"bytes32" 760 | }, 761 | { 762 | "internalType":"bytes32", 763 | "name":"commitment", 764 | "type":"bytes32" 765 | } 766 | ], 767 | "internalType":"struct Storage.StoredBlockInfo", 768 | "name":"_storedBlockInfo", 769 | "type":"tuple" 770 | }, 771 | { 772 | "internalType":"address", 773 | "name":"_owner", 774 | "type":"address" 775 | }, 776 | { 777 | "internalType":"uint32", 778 | "name":"_accountId", 779 | "type":"uint32" 780 | }, 781 | { 782 | "internalType":"uint32", 783 | "name":"_tokenId", 784 | "type":"uint32" 785 | }, 786 | { 787 | "internalType":"uint128", 788 | "name":"_amount", 789 | "type":"uint128" 790 | }, 791 | { 792 | "internalType":"uint32", 793 | "name":"_nftCreatorAccountId", 794 | "type":"uint32" 795 | }, 796 | { 797 | "internalType":"address", 798 | "name":"_nftCreatorAddress", 799 | "type":"address" 800 | }, 801 | { 802 | "internalType":"uint32", 803 | "name":"_nftSerialId", 804 | "type":"uint32" 805 | }, 806 | { 807 | "internalType":"bytes32", 808 | "name":"_nftContentHash", 809 | "type":"bytes32" 810 | }, 811 | { 812 | "internalType":"uint256[]", 813 | "name":"_proof", 814 | "type":"uint256[]" 815 | } 816 | ], 817 | "name":"performExodus", 818 | "outputs":[ 819 | 820 | ], 821 | "stateMutability":"nonpayable", 822 | "type":"function" 823 | }, 824 | { 825 | "inputs":[ 826 | { 827 | "components":[ 828 | { 829 | "internalType":"uint32", 830 | "name":"blockNumber", 831 | "type":"uint32" 832 | }, 833 | { 834 | "internalType":"uint64", 835 | "name":"priorityOperations", 836 | "type":"uint64" 837 | }, 838 | { 839 | "internalType":"bytes32", 840 | "name":"pendingOnchainOperationsHash", 841 | "type":"bytes32" 842 | }, 843 | { 844 | "internalType":"uint256", 845 | "name":"timestamp", 846 | "type":"uint256" 847 | }, 848 | { 849 | "internalType":"bytes32", 850 | "name":"stateHash", 851 | "type":"bytes32" 852 | }, 853 | { 854 | "internalType":"bytes32", 855 | "name":"commitment", 856 | "type":"bytes32" 857 | } 858 | ], 859 | "internalType":"struct Storage.StoredBlockInfo[]", 860 | "name":"_committedBlocks", 861 | "type":"tuple[]" 862 | }, 863 | { 864 | "components":[ 865 | { 866 | "internalType":"uint256[]", 867 | "name":"recursiveInput", 868 | "type":"uint256[]" 869 | }, 870 | { 871 | "internalType":"uint256[]", 872 | "name":"proof", 873 | "type":"uint256[]" 874 | }, 875 | { 876 | "internalType":"uint256[]", 877 | "name":"commitments", 878 | "type":"uint256[]" 879 | }, 880 | { 881 | "internalType":"uint8[]", 882 | "name":"vkIndexes", 883 | "type":"uint8[]" 884 | }, 885 | { 886 | "internalType":"uint256[16]", 887 | "name":"subproofsLimbs", 888 | "type":"uint256[16]" 889 | } 890 | ], 891 | "internalType":"struct ZkSync.ProofInput", 892 | "name":"_proof", 893 | "type":"tuple" 894 | } 895 | ], 896 | "name":"proveBlocks", 897 | "outputs":[ 898 | 899 | ], 900 | "stateMutability":"nonpayable", 901 | "type":"function" 902 | }, 903 | { 904 | "inputs":[ 905 | { 906 | "internalType":"uint32", 907 | "name":"_accountId", 908 | "type":"uint32" 909 | }, 910 | { 911 | "internalType":"address", 912 | "name":"_token", 913 | "type":"address" 914 | } 915 | ], 916 | "name":"requestFullExit", 917 | "outputs":[ 918 | 919 | ], 920 | "stateMutability":"nonpayable", 921 | "type":"function" 922 | }, 923 | { 924 | "inputs":[ 925 | { 926 | "internalType":"uint32", 927 | "name":"_accountId", 928 | "type":"uint32" 929 | }, 930 | { 931 | "internalType":"uint32", 932 | "name":"_tokenId", 933 | "type":"uint32" 934 | } 935 | ], 936 | "name":"requestFullExitNFT", 937 | "outputs":[ 938 | 939 | ], 940 | "stateMutability":"nonpayable", 941 | "type":"function" 942 | }, 943 | { 944 | "inputs":[ 945 | { 946 | "components":[ 947 | { 948 | "internalType":"uint32", 949 | "name":"blockNumber", 950 | "type":"uint32" 951 | }, 952 | { 953 | "internalType":"uint64", 954 | "name":"priorityOperations", 955 | "type":"uint64" 956 | }, 957 | { 958 | "internalType":"bytes32", 959 | "name":"pendingOnchainOperationsHash", 960 | "type":"bytes32" 961 | }, 962 | { 963 | "internalType":"uint256", 964 | "name":"timestamp", 965 | "type":"uint256" 966 | }, 967 | { 968 | "internalType":"bytes32", 969 | "name":"stateHash", 970 | "type":"bytes32" 971 | }, 972 | { 973 | "internalType":"bytes32", 974 | "name":"commitment", 975 | "type":"bytes32" 976 | } 977 | ], 978 | "internalType":"struct Storage.StoredBlockInfo[]", 979 | "name":"_blocksToRevert", 980 | "type":"tuple[]" 981 | } 982 | ], 983 | "name":"revertBlocks", 984 | "outputs":[ 985 | 986 | ], 987 | "stateMutability":"nonpayable", 988 | "type":"function" 989 | }, 990 | { 991 | "inputs":[ 992 | { 993 | "internalType":"bytes", 994 | "name":"_pubkeyHash", 995 | "type":"bytes" 996 | }, 997 | { 998 | "internalType":"uint32", 999 | "name":"_nonce", 1000 | "type":"uint32" 1001 | } 1002 | ], 1003 | "name":"setAuthPubkeyHash", 1004 | "outputs":[ 1005 | 1006 | ], 1007 | "stateMutability":"nonpayable", 1008 | "type":"function" 1009 | }, 1010 | { 1011 | "inputs":[ 1012 | { 1013 | "internalType":"uint32", 1014 | "name":"", 1015 | "type":"uint32" 1016 | } 1017 | ], 1018 | "name":"storedBlockHashes", 1019 | "outputs":[ 1020 | { 1021 | "internalType":"bytes32", 1022 | "name":"", 1023 | "type":"bytes32" 1024 | } 1025 | ], 1026 | "stateMutability":"view", 1027 | "type":"function" 1028 | }, 1029 | { 1030 | "inputs":[ 1031 | 1032 | ], 1033 | "name":"totalBlocksCommitted", 1034 | "outputs":[ 1035 | { 1036 | "internalType":"uint32", 1037 | "name":"", 1038 | "type":"uint32" 1039 | } 1040 | ], 1041 | "stateMutability":"view", 1042 | "type":"function" 1043 | }, 1044 | { 1045 | "inputs":[ 1046 | 1047 | ], 1048 | "name":"totalBlocksExecuted", 1049 | "outputs":[ 1050 | { 1051 | "internalType":"uint32", 1052 | "name":"", 1053 | "type":"uint32" 1054 | } 1055 | ], 1056 | "stateMutability":"view", 1057 | "type":"function" 1058 | }, 1059 | { 1060 | "inputs":[ 1061 | 1062 | ], 1063 | "name":"totalBlocksProven", 1064 | "outputs":[ 1065 | { 1066 | "internalType":"uint32", 1067 | "name":"", 1068 | "type":"uint32" 1069 | } 1070 | ], 1071 | "stateMutability":"view", 1072 | "type":"function" 1073 | }, 1074 | { 1075 | "inputs":[ 1076 | 1077 | ], 1078 | "name":"totalOpenPriorityRequests", 1079 | "outputs":[ 1080 | { 1081 | "internalType":"uint64", 1082 | "name":"", 1083 | "type":"uint64" 1084 | } 1085 | ], 1086 | "stateMutability":"view", 1087 | "type":"function" 1088 | }, 1089 | { 1090 | "inputs":[ 1091 | { 1092 | "internalType":"contract IERC20", 1093 | "name":"_token", 1094 | "type":"address" 1095 | }, 1096 | { 1097 | "internalType":"address", 1098 | "name":"_to", 1099 | "type":"address" 1100 | }, 1101 | { 1102 | "internalType":"uint128", 1103 | "name":"_amount", 1104 | "type":"uint128" 1105 | }, 1106 | { 1107 | "internalType":"uint128", 1108 | "name":"_maxAmount", 1109 | "type":"uint128" 1110 | } 1111 | ], 1112 | "name":"transferERC20", 1113 | "outputs":[ 1114 | { 1115 | "internalType":"uint128", 1116 | "name":"withdrawnAmount", 1117 | "type":"uint128" 1118 | } 1119 | ], 1120 | "stateMutability":"nonpayable", 1121 | "type":"function" 1122 | }, 1123 | { 1124 | "inputs":[ 1125 | { 1126 | "internalType":"bytes", 1127 | "name":"upgradeParameters", 1128 | "type":"bytes" 1129 | } 1130 | ], 1131 | "name":"upgrade", 1132 | "outputs":[ 1133 | 1134 | ], 1135 | "stateMutability":"nonpayable", 1136 | "type":"function" 1137 | }, 1138 | { 1139 | "inputs":[ 1140 | 1141 | ], 1142 | "name":"upgradeCanceled", 1143 | "outputs":[ 1144 | 1145 | ], 1146 | "stateMutability":"nonpayable", 1147 | "type":"function" 1148 | }, 1149 | { 1150 | "inputs":[ 1151 | 1152 | ], 1153 | "name":"upgradeFinishes", 1154 | "outputs":[ 1155 | 1156 | ], 1157 | "stateMutability":"nonpayable", 1158 | "type":"function" 1159 | }, 1160 | { 1161 | "inputs":[ 1162 | 1163 | ], 1164 | "name":"upgradeNoticePeriodStarted", 1165 | "outputs":[ 1166 | 1167 | ], 1168 | "stateMutability":"nonpayable", 1169 | "type":"function" 1170 | }, 1171 | { 1172 | "inputs":[ 1173 | 1174 | ], 1175 | "name":"upgradePreparationStarted", 1176 | "outputs":[ 1177 | 1178 | ], 1179 | "stateMutability":"nonpayable", 1180 | "type":"function" 1181 | }, 1182 | { 1183 | "inputs":[ 1184 | { 1185 | "internalType":"address payable", 1186 | "name":"_owner", 1187 | "type":"address" 1188 | }, 1189 | { 1190 | "internalType":"address", 1191 | "name":"_token", 1192 | "type":"address" 1193 | }, 1194 | { 1195 | "internalType":"uint128", 1196 | "name":"_amount", 1197 | "type":"uint128" 1198 | } 1199 | ], 1200 | "name":"withdrawPendingBalance", 1201 | "outputs":[ 1202 | 1203 | ], 1204 | "stateMutability":"nonpayable", 1205 | "type":"function" 1206 | }, 1207 | { 1208 | "inputs":[ 1209 | { 1210 | "internalType":"uint32", 1211 | "name":"_tokenId", 1212 | "type":"uint32" 1213 | } 1214 | ], 1215 | "name":"withdrawPendingNFTBalance", 1216 | "outputs":[ 1217 | 1218 | ], 1219 | "stateMutability":"nonpayable", 1220 | "type":"function" 1221 | } 1222 | ] -------------------------------------------------------------------------------- /src/test/resources/abiFiles/uniswapV3Router-input/input_0xeb154fb38972106bfc0e9bce28130379c44d80be292de775e0f43e2c861e0f48: -------------------------------------------------------------------------------- 1 | 0xc04b8d59000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000009e3df1cd92386519734558178e535e0460b10ab60000000000000000000000000000000000000000000000000000000064e31e750000000000000000000000000000000000000000000000000001c6bf5263400000000000000000000000000000000000000000000000000000000000000cdfb20000000000000000000000000000000000000000000000000000000000000042c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000bb8514910771af9ca656af840dff83e8264ecf986ca000bb8dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000000000000000000000000000000000000000 -------------------------------------------------------------------------------- /src/test/resources/logback-test.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n 8 | 9 | 10 | 11 | 12 | 13 | 14 | --------------------------------------------------------------------------------