What Changed in Web3j’s Solidity Gradle Plugin and Sokt: Faster Compiler Resolution, ARM64 Support, and New Build Controls
As a mentee in the Web3j Libraries Full Development Lifecycle project under the LF Decentralized Trust Mentorship Program, I worked on improving the tooling that connects Solidity contracts with Java and Kotlin applications. This work focused on Sokt and the Web3j Solidity Gradle Plugin, improving Solidity compiler resolution, adding ARM64 support, making Gradle builds more reliable, and introducing new Solidity DSL options for better build control.
These improvements address common issues faced by JVM-based Solidity developers, including delays in supporting new Solidity releases, reliance on x86 compiler emulation on ARM64 systems, build failures in projects without contracts or with custom contract directories, and manual setup of remappings for third-party contract packages.
If you write smart contracts and use them from the JVM, the Web3j Solidity Gradle Plugin converts .sol files into generated contract wrappers. It relies on Sokt, a library that resolves and installs the required solc compiler version. The key change in Sokt was moving compiler version lookup from a project-maintained list to Solidity’s official binary indexes, which improves reliability and allows the plugin to build on a more robust foundation.
Setting up the plugin
Applying the plugin looks the same as it always has. With the Groovy DSL, in build.gradle:

or with the Kotlin DSL, in build.gradle.kts:

Drop your contracts under src/main/solidity, and a normal build will compile them and generate the wrappers. Custom source directories are supported too, with the documented configuration syntax recently corrected and covered by a test. That is the starting point, and everything that follows builds on it.
Sokt: from static compiler lists to upstream Solidity indexes
Sokt now resolves compiler versions using Solidity’s official platform-specific binary indexes instead of relying only on Web3j’s maintained releases.json. This removes the need for a new Sokt release whenever Solidity publishes a new compiler version. Previously, every new solc release required updating the internal release list and publishing a new Sokt version before developers could use it.
Sokt now uses Solidity’s official compiler indexes at binaries.soliditylang.org to resolve and download the required solc version. The compiler is cached under ~/.web3j/solc/ for reuse in future builds. This allows new Solidity releases to be supported immediately through the upstream index without waiting for a Sokt update. A bundled releases.json remains available as a fallback for offline or unavailable network scenarios.
For standard builds, there is nothing new to configure. You target a version explicitly:

or by letting the plugin read it from the pragma in your contract:
![]()
On the first build for a version you do not have yet, you will see the compiler being resolved and fetched, and then your contracts compile against it.

Sokt resolving and installing solc 0.8.35 on first use.
The bundled releases.json provides an offline fallback when the network is unavailable, allowing Sokt to continue working without fetching the Solidity release list remotely.
Previously, the fallback mechanism could fail under isolated classloaders, especially when Sokt ran as a Gradle plugin, because the resource was not loaded through Sokt’s own classloader.
PR #45 fixes this by using Sokt’s classloader to load the bundled release list, ensuring the offline fallback works reliably in both CLI and Gradle environments. The bundled list was also updated with recent Solidity releases.
Related pull requests: web3j-sokt #43, web3j-sokt #45
Native Linux ARM64 compiler support
The plugin now supports architecture-aware compiler selection. It detects the machine architecture during compiler resolution and automatically selects native Linux ARM64 Solidity binaries for Solidity 0.8.31 and, later, where upstream ARM64 builds are available. For older Solidity versions and non-ARM64 platforms, the existing compiler selection behaviour remains unchanged.
This allows ARM64 environments, such as Linux on Apple Silicon or AWS Graviton CI instances, to use native Solidity compilation instead of running x86 binaries through emulation. No additional configuration or flags are required.
Related pull request: web3j-solidity-gradle-plugin #90
More reliable Gradle builds
Two reliability improvements address common Gradle project setups.
First, the plugin now handles projects with no Solidity sources. Previously, applying the plugin to an empty module or one without sol files could fail during task validation. The updated behavior allows such projects to build successfully.
Second, custom Solidity source directory configuration has been fixed and tested. Projects using locations other than src/main/solidity can now configure them correctly through the sourceSets DSL, with the updated documentation example covered by integration tests.

And with the Kotlin DSL, the source path is set with srcDir("my/custom/path/to/solidity"). One thing worth clearing up: allowPaths controls Solidity import resolution only and does not replace your source directories, so it is not the property to reach for here.
Related pull requests: web3j-solidity-gradle-plugin #91, web3j-solidity-gradle-plugin #92
New options in the Solidity DSL
The remaining improvements are options you opt into. Each one lives in the same solidity { } block you already use for compiler options like optimize and evmVersion. Here is a quick summary before the details:

New Solidity DSL option: packages
Many Solidity projects import contracts from npm packages such as @openzeppelin/contracts. The plugin already detected scoped imports, the @scope/name form, written directly in your .sol files, but only those, and it always resolved them at their latest version. Anything it did not detect, or any specific version you needed, had to be wired up by hand with pathRemappings.
The new packages option lets you declare the packages you want directly, with an optional version to pin. They are added to the generated package.json, installed, and remapped for you:

A version you declare here takes precedence over one detected from imports, so you can lock a dependency to a known-good release instead of always tracking the latest. Automatic detection still works alongside this, so you only list the packages you want to control, and there is no need to disable resolvePackages or manage pathRemappings yourself.
Related pull request: web3j-solidity-gradle-plugin #93
New Solidity DSL option: viaIr
Some contracts fail to compile with Solidity’s classic code generator and report a Stack too deep error. The usual fix is to compile through Solidity’s IR-based pipeline, which routes your code through the Yul intermediate representation and enables the full Yul optimizer.
You can now turn that on with a single flag:

When it is enabled, the plugin passes --via-ir to the compiler. It defaults to off, so existing builds are untouched. Reach for it when a contract hits Stack too deep, or when you want the extra optimization the IR pipeline enables. Like the other compiler options, it can also be set per source set, which helps when only one module or contract group needs IR compilation, and you want the rest to keep the default compiler pipeline:

If you have ever dropped out of Gradle to compile a stubborn contract by hand, this is the option that lets you stay in your normal build.
Related pull request: web3j-solidity-gradle-plugin #95
New Solidity DSL option: compilerEnabled
Not all projects require Solidity compilation. Some only need Java or Kotlin wrappers from existing .abi files, such as CI jobs or projects with precompiled contracts. Previously, applying the plugin still included unnecessary Solidity compiler and Node/npm dependencies.
Setting compilerEnabled = false skips all of that:

With this flag disabled, the compile step is skipped, meaning no solc is resolved or downloaded. The Node and npm dependency chain is also removed from the task graph, so these tools are not required. This helps simplify and speed up CI builds for projects that only generate wrappers from existing artifacts.
compilerEnabled = false only skips Solidity compilation; it does not generate ABI files. Existing compiled artifacts (.abi and matching .bin) must be provided under build/resources/solidity/<sourceSet>. The generateContractWrappers task, which is part of the Web3j Gradle plugin and applied alongside the Solidity plugin to handle the wrapper generation flow, then converts these files into Java or Kotlin wrappers under build/generated/sources/web3j. This flag only removes compilation and package-resolution steps.
If Solidity compilation is still required but Node/npm package resolution is not, use resolvePackages = false, which only disables third-party package handling.
Related pull request: web3j-solidity-gradle-plugin #96
Wrapping up
Put together, these changes tighten the path from Solidity source to JVM wrapper. Compiler resolution now tracks Solidity’s official binary indexes, so new releases are usable as soon as they are published; ARM64 machines get native compilers with no configuration; the compiler fallback survives the isolated classloaders that Gradle plugins run under; and builds hold up on empty and custom source layouts. On top of that, packages, viaIr, and compilerEnabled give you declarative control over dependency resolution, IR compilation, and wrapper-only or CI builds.
The best way to get a feel for them is to try them on a real project. Update to the released plugin version 0.7.1 that includes these changes, point a build at a recent Solidity version and watch it resolve automatically, pin a package, flip on viaIr for a contract that has been giving you Stack too deep, or set compilerEnabled = false in a wrapper-only job. If something does not behave the way you expect, that feedback is genuinely useful, so please share it. You can ask questions and report issues in the web3j Discord, explore the wider community in the LF Decentralized Trust Discord, or join a community call to see what the maintainers are working on next.
Thanks to the Web3j maintainers and mentors for the reviews and guidance that shaped this work.