Skip to main content

Hello World

The hello world example demonstrates how to write a simple contract, with a single function that takes one input and returns it as an output.

Run the Example

First go through the Setup process to get your development environment configured, then clone the v0.0.4 tag of soroban-examples repository:

git clone -b v0.0.4 https://github.com/stellar/soroban-examples

To run the tests for the example, navigate to the hello_world directory, and use cargo test.

cd hello_world
cargo test

You should see the output:

running 1 test
test test::test ... ok

Code

hello_world/src/lib.rs
#![no_std]
use soroban_sdk::{contractimpl, symbol, vec, Env, Symbol, Vec};

pub struct HelloContract;

#[contractimpl]
impl HelloContract {
pub fn hello(env: Env, to: Symbol) -> Vec<Symbol> {
vec![&env, symbol!("Hello"), to]
}
}

Ref: https://github.com/stellar/soroban-examples/tree/v0.0.4/hello_world

How it Works

Soroban contracts export all public functions that are within impl blocks that have been annotated with #[contractimpl]. In the example above the contract exports a single function, hello.

Contract functions must be given names that are no more than 10 characters long.

Open the hello_world/src/lib.rs file to follow along.

Contract Type

Contract functions must be defined within an impl block, and therefore a type is required for the impl to be attached. A simple zero-sized struct can be used.

pub struct HelloContract;

Contract Function

Contract functions look much like regular Rust functions. They mave have any number of arguments, but arguments must support being transmitted to and from the Soroban environment that the contract runs in. The Soroban SDK provides some types like Vec, Map, BigInt, Symbol, Bytes, BytesN, etc that can be used. Primitive values like u64, i64, u32, i32, and bool can also be used. Floats are not supported.

Contract inputs must not be references.

If the first argument of a contract function is of the soroban_sdk::Env type, an Env will be provided that provides access to additional functionality. Most functionality within the SDK requires an Env, so it is recommended to have it in the argument list for most functions.

#[contractimpl]
impl HelloContract {
pub fn hello(env: Env, to: Symbol) -> Vec<Symbol> {
...
}
}

Tests

Open the hello_world/src/test.rs file to follow along.

hello_world/src/test.rs
#[test]
fn test() {
let env = Env::default();
let contract_id = BytesN::from_array(&env, &[0; 32]);
env.register_contract(&contract_id, HelloContract);
let client = HelloContractClient::new(&env, &contract_id);

let words = client.hello(&symbol!("SourBun"));
assert_eq!(words, vec![&env, symbol!("Hello"), symbol!("Dev"),]);
}

In any test the first thing that is always required is an Env, which is the Soroban environment that the contract will run in.

let env = Env::default();

Contracts must be registered with the environment with a contract ID, which is a 32-byte value.

let contract_id = FixedBinary::from_array(&env, [0; 32]);
env.register_contract(&contract_id, HelloContract);

All public functions within an impl block that is annotated with the #[contractimpl] attribute have a corresponding function generated in a generated client type. The client type will be named the same as the contract type with Client appended. For example, in our contract the contract type is HelloContract, and the client is named HelloContractClient.

let client = HelloContractClient::new(&env, &contract_id);
let words = client.hello(&symbol!("Dev"));

The values returned by functions can be asserted on:

assert_eq!(words, vec![&env, symbol!("Hello"), symbol!("Dev"),]);

Build the Contract

To build the contract, use the cargo build command.

cargo build --target wasm32-unknown-unknown --release

A .wasm file should be outputted in the ../target directory:

../target/wasm32-unknown-unknown/release/soroban_hello_world_contract.wasm

Run the Contract

If you have [soroban-cli] installed, you can invoke contract functions in the using it.

soroban-cli invoke \
--wasm ../target/wasm32-unknown-unknown/release/soroban_hello_world_contract.wasm \
--id 1 \
--fn hello \
--arg friend

The following output should occur using the code above.

["Hello","friend"]