Build

Quick Start

Build and deploy your first Vara.eth program in 5 minutes.

Quick Start

This guide takes you from zero to a deployed program on Vara.eth testnet. You'll create a simple counter program, deploy it to Ethereum Hoodi, and interact with it.

Prerequisites

Rust toolchain, Sails CLI, and ethexe CLI installed. → Tools Install

1. Create a New Project

cargo sails new counter-app
cd counter-app

This scaffolds a new Sails program with the correct project structure.

2. Write Your Program

Open app/src/lib.rs and replace the contents with:

app/src/lib.rs
#![no_std]

use sails_rs::prelude::*;

// Program state
static mut COUNTER: i64 = 0;

// Service definition — your program's API
#[derive(Default)]
pub struct CounterService;

#[service]
impl CounterService {
    /// Increment the counter and return the new value
    pub fn increment(&mut self) -> i64 {
        unsafe {
            COUNTER += 1;
            COUNTER
        }
    }

    /// Decrement the counter and return the new value
    pub fn decrement(&mut self) -> i64 {
        unsafe {
            COUNTER -= 1;
            COUNTER
        }
    }

    /// Read the current counter value
    pub fn get(&self) -> i64 {
        unsafe { COUNTER }
    }
}

// Program entry point
#[derive(Default)]
pub struct CounterProgram;

#[program]
impl CounterProgram {
    /// Constructor — called once when the program is initialized
    pub fn init() -> Self {
        Self
    }

    /// Expose the CounterService
    pub fn counter(&self) -> CounterService {
        CounterService
    }
}

Why static mut is acceptable here

In Vara.eth's actor model, each program processes messages sequentially (single-threaded execution per program), so this simple static mut counter example does not have concurrent access. For production contracts and richer state, prefer structured state patterns in Sails services.

Update Cargo.toml to enable ethexe support:

Cargo.toml
[package]
name = "counter-app"
version = "0.1.0"
edition = "2021"

[dependencies]
sails-rs = { version = "0.10.1", features = ["ethexe"] }
parity-scale-codec = { version = "3", default-features = false }
scale-info = { version = "2", default-features = false }

3. Build

cargo build --release

This produces two artifacts in target/wasm32-gear/release/:

4. Deploy to Testnet

Set up your environment:

# Insert your private key (testnet wallet only!)
ethexe key insert <YOUR_PRIVATE_KEY>

# Set variables for convenience
export RPC="wss://hoodi-reth-rpc.gear-tech.io/ws"
export ROUTER="0xBC888a8B050B9B76a985d91c815d2c4f2131a58A"
export SENDER="<YOUR_WALLET_ADDRESS>"

Router Address Source

For the latest network addresses, always check Contract Addresses.

Upload the WASM code

ethexe tx upload target/wasm32-gear/release/counter_app.opt.wasm \
  --watch \
  --ethereum-rpc "$RPC" \
  --ethereum-router "$ROUTER" \
  --sender "$SENDER"

This uploads your WASM as an EIP-4844 blob and requests code validation. Wait for the CODE_ID to appear in the output.

export CODE_ID="0x..."  # Copy from output

Create a program instance

ethexe tx create "$CODE_ID" \
  --salt 0x0000000000000000000000000000000000000000000000000000000000000001 \
  --ethereum-rpc "$RPC" \
  --ethereum-router "$ROUTER" \
  --sender "$SENDER"

This deploys a Mirror contract on Ethereum representing your program. The output contains your PROGRAM_ID (Mirror address).

export PROGRAM_ID="0x..."  # Copy from output

Deterministic Addressing

The --salt parameter makes the Mirror address deterministic. Use different salts to deploy multiple instances of the same code. Address is computed as CREATE2(Router, keccak256(codeId, salt)).

Fund the program

Your program needs wVARA to pay for execution. Use the executableBalanceTopUp function on the Mirror contract via Etherscan, the SDK, or CLI.

Funding Executable Balance

Initialize the program

Send the first message to trigger the constructor:

ethexe tx send-message "$PROGRAM_ID" "0x..." 0 \
  --ethereum-rpc "$RPC" \
  --ethereum-router "$ROUTER" \
  --sender "$SENDER"

5. Interact with Your Program

Once initialized, anyone can send messages to your program. The Mirror contract on Ethereum accepts standard transactions.

Interact via:

  • Etherscan — If you deployed with an ABI interface, methods appear under "Write as Proxy"
  • CLI — Use ethexe tx send-message
  • SDK — Use sails-js or @vara-eth/api from your frontend

Read state

ethexe tx query "$PROGRAM_ID" \
  --ethereum-rpc "$RPC" \
  --ethereum-router "$ROUTER" \
  --sender "$SENDER"

What Just Happened?

You completed the core lifecycle:

  1. Build and upload code
  2. Create Mirror instance
  3. Fund executable balance
  4. Initialize and interact

Your program is now live on Ethereum via its Mirror address.

→ Full lifecycle details: Program Basics
→ API/design structure: Sails Workflow

On this page