DEV Community

yuzurush
yuzurush

Posted on • Updated on

Soroban Contracts 101 : Hello World

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 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

#![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]
    }
}
Enter fullscreen mode Exit fullscreen mode

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"),]);
}
Enter fullscreen mode Exit fullscreen mode

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 Symbols 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
Enter fullscreen mode Exit fullscreen mode

If the tests are successful, you should see an output similar to:

running 1 test
test test::test ... ok
Enter fullscreen mode Exit fullscreen mode

Building The Contract

To build the contract, use the following command:

cargo build --target wasm32-unknown-unknown --release
Enter fullscreen mode Exit fullscreen mode

This should output a .wasm file in the ../target directory:

../target/wasm32-unknown-unknown/release/soroban_hello_world_contract.wasm
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

You should see the following output:

["Hello", "World"]
Enter fullscreen mode Exit fullscreen mode

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.

Top comments (0)