Soroban Contracts 101 : Hello World
Tags: soroban, sorobanathon, sorobanathonequinox, stellar
Published: 2023-03-11 13:15:22

Hi there! Welcome to my first post on Dev.to. This is the beginning of my series called "Soroban Contracts 101", where I'll be explaining the basics of Soroban contracts, such as data storage, authentication, custom types, and more. All the code that we're gonna explain throughout this series will mostly come from [soroban-contracts-101](https://github.com/yuzurush/soroban-contracts-101) github repository.

In this first post of the series, I'll be covering one of the most fundamental concepts in the programming world - "Hello World". Traditionally, it's the first program developers use to test a system. This will introduce you to Soroban Contracts, give you an idea of what Soroban Contracts are and how they work.

##The Contract Code
```rust
#![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]
    }
}
```

The `#![no_std]` directive at the beginning of the code indicates that the Rust standard library is not included in the build to keep the code lightweight and efficient.

The code imports the necessary modules from the Soroban SDK using the `use` keyword. These modules include `contractimpl`, `symbol`, `vec`, `Env`, `Symbol`, and `Vec`.

The HelloContract zero-sized struct is used as a placeholder to specify the name of the contract.

The `#[contractimpl]` attribute indicates that the following code block is a Soroban Contract implementation. The `hello()` function is the main part of the contract, which takes two arguments: `env` of type `Env` and `to` of type `Symbol`. The `Env` type provides access to the contract's environment, while `Symbol` represents an encoded string with maximum length of 10.

The function returns a vector of Symbols containing the env, "Hello", and `to` values that will be supplied when function invoked. 

##The Test Code

```
#[test]
fn test() {
    let env = Env::default();
    let contract_id = env.register_contract(None, HelloContract);
    let client = HelloContractClient::new(&env, &contract_id);

    let words = client.hello(&symbol!("SourBun"));
    assert_eq!(words, vec![&env, symbol!("Hello"), symbol!("Dev"),]);
}
```
This code is a test module for the "Hello World" Soroban Contract. It uses the `#[cfg(test)]` attribute to denote that this code is only meant to run during testing.

The code imports the `super::*` module, which allows the test module to access the contract implementation in the parent module. It also imports modules from the soroban_sdk library, including `symbol`, `vec`, and `Env`.

The `test()` function is the main part of the test module. It begins by creating a default `Env` object, which represents the contract's environment. It then registers the `HelloContract` without a name, which is represented by `None`, and returns its unique contract ID. The `HelloContractClient` is then created using the `Env` object and the contract ID.

The `client.hello()` function is called with the argument `symbol!("Dev")`, which represents an encoded string. The `hello()` function returns a vector of `Symbol`s containing the `Env`, `"Hello"`, and `"Dev"` values.

Lastly, the code uses the `assert_eq!()` macro to compare the expected output of the `hello()` function with the actual output. If the two are not equal, the test fails. This ensures that the `hello()` function is working as expected.

Testing contract code is an essential step in the development process to ensure that our contract is working correctly before deploying it to the blockchain.

##Running Contract Tests
To ensure that the contract functions as intended, you can run the contract tests using the following command:
```
cargo test
```
If the tests are successful, you should see an output similar to:
```
running 1 test
test test::test ... ok
```

##Building The Contract
To build the contract, use the following command:
```
cargo build --target wasm32-unknown-unknown --release
```
This should output a .wasm file in the ../target directory:
```
../target/wasm32-unknown-unknown/release/soroban_hello_world_contract.wasm
```

##Invoking The Contract
To invoke the `hello` function of the contract with a `to` value supplied as a string, use the following command with Soroban-CLI:
```
soroban contract invoke \
    --wasm ../target/wasm32-unknown-unknown/release/soroban_hello_world_contract.wasm \
    --id 1 \
    -- \
    hello \
    --to World
```
You should see the following output:
```
["Hello", "World"]
```
Therefore, the output ["Hello", "World"] indicates that the hello function was successfully invoked with the specified `to` value, and that the function executed as intended, returning the expected array of strings.

## Conclusion
In this first post of the series, we introduced you to Soroban Contracts by explaining "Hello World" contract. We hope this article has given you an idea of what Soroban Contracts are and how they work. Stay tuned for more post in this "Soroban Contracts 101" Series where we will dive deeper into Soroban Contracts and their functionalities.