Skip to main content

Welcome to the Cubist docs!

Cubist is an SDK and command line tool for building distributed web3 applications. Dive in with our easy example app!

Cubist’s goal is to make testing and development seamless, even if your dapp runs across multiple chains. Using our SDK, you write smart contracts as if they're deployed on the same chain; Cubist automatically generates the tricky (and risky!) bridge code that allows your smart contracts to interact.

What version of Cubist is this release?

Cubist alpha version 0.2.1-alpha.


Cubist is currently in its alpha release. APIs may change in the future, and you should not use Cubist to deploy apps to mainnet (yet)!

What chains and languages does Cubist support?

Cubist supports off-chain code written in:

  • JavaScript
  • TypeScript
  • and Rust

Cubist supports development and deployment for:

  • Ethereum
  • Polygon
  • Avalanche
  • and Avalanche subnets

Support for more chains and more off-chain languages coming soon!

What Cubist tools do I need to get started?

There are two pieces you need to use Cubist:

  • The Cubist CLI tool. The CLI tool is what you use to build your projects, run chains locally for testing, run the Cubist relayer, etc.
  • The Cubist SDK. The SDK is what you use to interact with your contracts from off the chain; right now, there's a Java/TypeScript SDK and a Rust SDK. Typically, you won't use the SDK directly. Instead, when you use the CLI to cubist build your project, Cubist will generate ORM code that makes it easy to interface with your contracts. This ORM code is built from (and exposes) SDK functions. You can learn more by checking out our example applications or the Node SDK and Rust SDK docs.

What does cross-chain code look like using Cubist?

With Cubist, cross-chain contracts look exactly like single-chain contracts; Cubist automatically generates the cross-chain code that allows the contracts to interact.

What's an example of cross-chain code using Cubist?

Consider an application that exposes a number stored across two different chains. The sender contract stores a number and then sends it to the receiver contract; the receiver contract stores the number, too.

Here's an example of the sender contract:

import './StorageReceiver.sol';

contract StorageSender { // deployed on one chain

StorageReceiver receiver; // deployed on a different chain
uint256 number;

constructor (uint256 num, StorageReceiver addr) {
number = num;
receiver = addr;

function store(uint256 num) public onlyOwner {
number = num;; // cross-chain call

Even though the sender contract and receiver contract are deployed on different chains, we can write them as if they're deployed on the same chain. Cubist will analyze the contracts and emit extra code and contracts that allow to actually send the number from one chain to another.

What are the limitations of Cubist's cross-chain support?

Right now, Cubist can only generate cross-chain code for public functions with no return values.


If you're interested in support for other types of functions, reach out to us at [email protected] or on discord.

How do I change chains?

You can change the chain on which your contract runs by editing a configuration file. Your cubist-config.json will look something like this:

"targets": {
"ethereum" : {
"files": ["./contracts/StorageReceiver.sol"]
"polygon": {
"files": ["./contracts/StorageSender.sol"]

This tells Cubist that StorageReceiver.sol should be deployed on Ethereum and StorageSender.sol should be deployed on Polygon. Changing polygon to avalanche would direct Cubist to deploy StorageSender on Avalanche instead.

How do I change bridge providers?

Right now, the only relayer available is the Cubist Trusted Relayer. Our next release will support the Axelar bridge provider (and potentially others as well). Changing bridge providers will be the same as changing chains---just a matter of editing the configuration file.


Reach out at [email protected] or on discord if you're interested in new bridge provider support!

How does Cubist generate cross-chain code?

Given your contract source code and intended targets for each file, Cubist analyzes each contract. For example, in the StorageSender contract above, Cubist determines that StorageSender uses the StorageReceiver contract in StorageReceiver.sol. Cubist knows that StorageReceiver is deployed on Chain B, while StorageSender is deployed on Chain A. Since StorageSender calls StorageReceiver, Cubist generates a "shim" contract that exposes StorageReceiver to Chain A. Anytime StorageSender calls a StorageReceiver function, it's actually calling the Chain A shim's version of the function. The shim function emits events that the Cubist relayer uses to relay function calls to the "real" StorageReceiver contract on Chain B. There are more detailed walk-throughs in the advanced examples.