# 1 lesson: Hello world program
Smart Contract is an equivalent of a microservice which is stored on the blockchain network and is the essential building block of a decentralized application.
One of the features of the Gear protocol is the `Actor model` for message-passing communication. The principles of `Actor model`:
- Actors are modeled as independent computational entities.
- The immutable messages are used to communicate between actors.
- Actors do not share state and if any information is shared, it’s done via message only. Actors control access to the state and nobody else can access their state. This means there is no shared, mutable state.
<center>
<img src="https://i.imgur.com/lZaVIyR.png" width=500>
</center>
Each actor has a queue attached where the incoming messages are enqueued. Messages are picked from the queue and processed by the actor, one at a time. An actor can respond to the received message by sending immutable messages to other actors. It can also create a new set of actors or update its own state.
<center>
<img src="https://i.imgur.com/CVVytx3.png" width=350>
</center>
The Actor is a single instantiation of a contract, which can perform several actions.
When the message is sent to the contract, one of the entry points is called.
A contract contains up to 3 entry points the perform various functions during the program life cycle:
- `init()` - is called once per smart contract life time:
```
#[no_mangle]
extern "C" fn init() {}
```
- `handle()` - is called every time the program receives an incoming message.
```
#[no_mangle]
extern "C" fn handle() {}
```
- `handle_reply()` - is used for processing the reply to the sent message.
```
#[no_mangle]
extern "C" fn handle_reply() {}
```
### 1 part
We will create our first smart contract program called "Hello World."
Open in gitpod: https://github.com/LouiseMedova/starter.
Install the tools required to build smart contract in Rust. Gitpod always comes with the latest available Rust toolchain pre-installed using Rust compiler``rustup``. Let's install a nightly version of the toolchain with``rustup``:
```
rustup toolchain add nightly
```
As we will be compiling our Rust smart contract to Wasm, we will need a Wasm compiler. Let's add it to the toolchain:
```
rustup target add wasm32-unknown-unknown --toolchain nightly
```
Let's declare entry points in `lib.rs` file:
```
#![no_std]
use gstd::{prelude::*};
#[no_mangle]
extern "C" fn init() {}
#[no_mangle]
extern "C" fn handle() {}
```
and build the project:
```
cargo build --release
```
Let's import `msg` module from `gstd` library.
```
use gstd::{prelude::*, msg};
```
The `msg` module allows users to process incoming messages, obtain the necessary information about the sender or the message content, and send replies or new messages to other actors.
We'll use the `reply` function that sends a new message as a reply to the message currently being processed:
```
#[no_mangle]
extern "C" fn handle() {
msg::reply(String::from("Hello"), 0).expect("Error in sending a reply message");
}
```
The first argument is the payload. The second argument is the value to be transferred from the current program account to the reply message target account.
Let's write a simple test.We'll create a new directory called `tests` at the top level of our project directory, next to the `src` director. In that directory, we’ll create a file `hello_world_test.rs` where we’ll write tests for our contract.
```
mkdir tests
cd tests
touch hello_world_test.rs
```
In our test file, we’ll need to import the necessary modules from the gtest library:
```
use gtest::{Log, Program, System};
```
We’ll also define a test function:
```
#[test]
fn hello_test() {}
```
Before testing our smart contract, we need to initialize the environment for running programs. We can do this using the System module from gtest. The system emulates the node behaviour:
```
let sys = System::new();
```
Next, we need to initialize our program.
```
let hello_program = Program::current(&system);
```
The uploaded program has its own id. You can specify the program id manually using the `current_with_id` constructor.
```
let hello_program = Program::current_with_id(&system, 100);
```
If you don't specify the program id, the id of the first initialized program will be `1`, and the next program initialized without an id specification will have the second id and so on.
In the next step, we’ll send messages to our program.
```
hello_program.send(10, String::from("Init message"));
```
The first argument in the `send` is a sender id, the second one is a message payload.
The first message to the program in `gtest` is also the init message.
Let's go to the `lib.rs` file and add the proccessing of the incoming message:
```
#![no_std]
use gstd::{prelude::*, msg, debug};
#[no_mangle]
extern "C" fn init() {
let init_message: String = msg::load().expect("Can't load the incoming message");
debug!("Program initialized {:?}", init_message);
}
```
Let's also add `init_logger()` to initialize printing logs into stdout:
```
#[test]
fn hello_world() {
let system = System::new();
system.init_logger();
let hello_program = Program::current_with_id(&system, 100);
hello_program.send(10, String::from("Init message"));
}
```
and run the test:
```
cargo test --release
```
If everything is working correctly, we should see the debug message in our console:
```
running 1 test
[DEBUG hello_world] Program initialized "Init message"
test hello_world ... ok
```
Sending functions in the gtest library will return RunResult structure. It contains the final result of the processing message and others, which were created during the execution.
```
let res = hello_program.send(10, String::from("Init message"));
```
We check that the result of the proccessing the message was successful:
```
static mut GREETING: Option<String> = None;
```
Let's send the next message to our program.
```
let res = hello_program.send(10, String::from("Handle message"));
assert!(!res.main_failed());
```
This message will be proccessed through the handle function. Let's add `debug` to the `handle` and run the test:
```
#[no_mangle]
extern "C" fn handle() {
debug!("Handle");
msg::reply(String::from("Hello"), 0).expect("Error in sending a reply message");
}
```
Here we should check that the program replied with `hello` message.
```
let decoded_reply = res.decoded_log::<String>();
println!("{:#?}", decoded_reply);
```
Since the message payload is `String`, we indicate the type `String` in the `decoded_log` function.
To see the output from print statements, we run the tests with the nocapture flag:
```
cargo test --release -- --nocapture
```
We can see that we've received a message from the program with `Hello` payload:
```
[
DecodedCoreLog {
id: MessageId(0x3c95446e19b23ce659fa6e5cec08e814af11d18cc2ec26378f98e3aa31d6882d),
source: ProgramId(0x6400000000000000000000000000000000000000000000000000000000000000),
destination: ProgramId(0x0a00000000000000000000000000000000000000000000000000000000000000),
payload: "Hello",
status_code: Some(
0,
),
},
]
```
Usually in tests we don't need to print the result, but check that the result contains the expected message.
To do this, we can use the Log structure from the gtest lib and build the log we are expecting to receive. Specifically, we can use the `Log` structure from the `gtest`lib:
```
use gtest::{System, Program, Log};
#[test]
fn hello_world() {
...
let expected_reply = Log::builder().dest(10).payload(String::from("Hello"));
assert!(res.contains(&expected_reply));
}
```
Run the test and make sure that everything is fine.
### 2 part
Let’s add more functionality to our program by introducing two new messages: `SendHelloTo` and `SendHelloReply`.
Our program will receive 2 messages:
- `SendHelloTo`: having received this message, the program will send `hello` to the specified address;
- `SendHelloReply`: the program replies with a `hello` message to the account that sent the current message.
As we saw from the previous lesson, we’ll have to decode the message the program received. We’ll define an enum InputMessages that will be used to decode the incoming message.
```
#[derive(Encode, Decode, TypeInfo, Debug)]
pub enum InputMessage {
SendHelloTo(ActorId),
SendHelloReply,
}
```
The SendHelloTo variant includes an ActorId field where the program will send the hello message.
We also need to add derive macros ``#[derive(Encode, Decode, TypeInfo)]`` to the enum for encoding and decoding in messages.
We’ll also define a static mutable variable `GREETING` as an `Option<String>``.
```
static mut GREETING: Option<String> = None;
```
Until the program is initialized, the `GREETING` equals `None`. After the initialization, the `GREETING` will become `Some(String)`.
```
#[no_mangle]
extern "C" fn init() {
let init_message: String = msg::load().expect("Can't load the incoming message");
debug!("Program initialized {:?}", init_message);
unsafe { GREETING = Some(init_message)};
}
```
Next, we’ll decode the incoming message in the handle function and define the message the program received:
```
#[no_mangle]
extern "C" fn handle() {
let message: InputMessage = msg::load().expect("Can't decode `InputMessage`");
debug!("Incoming message {:?}", message);
let greeting = unsafe { GREETING.as_ref().expect("The contract is not initialized")};
match message {
InputMessage::SendHelloTo(account) => {
msg::send(account, greeting, 0).expect("Can't send a `SendHelloTo` message");
},
InputMessage::SendHelloReply => {
msg::reply(greeting, 0).expect("Can't send a `SendHelloReply` message");
}
}
}
```
Let's test our updated contract:
```
#[test]
fn hello_world() {
let system = System::new();
system.init_logger();
let hello_program = Program::current_with_id(&system, 100);
let greeting = String::from("Hello world!");
let res = hello_program.send(10, greeting.clone());
assert!(!res.main_failed());
let recipient = 200;
let res = hello_program.send(10, InputMessage::SendHelloTo(recipient.into()));
let expected_log = Log::builder().dest(recipient).payload(greeting.clone());
assert!(res.contains(&expected_log));
let expected_msg = res.decoded_log::<String>();
println!("{:#?}", expected_msg);
let res = hello_program.send(10, InputMessage::SendHelloReply);
let expected_log = Log::builder().dest(10).payload(greeting.clone());
assert!(res.contains(&expected_log));
let expected_msg = res.decoded_log::<String>();
println!("{:#?}", expected_msg);
}
```
### 3 part
Next step is to upload the program to the chain. But before it we should learn the program `metadata`. `Metadata` helps the client side of dApp to understand the smart contract interface.
Let's create a crate for metadata:
```
cargo new io --lib
```
The `Cargo.toml` file of the `io` crate:
```
[package]
name = "hello-world-io"
version = "0.1.0"
edition = "2021"
[dependencies]
gstd = { git = "https://github.com/gear-tech/gear.git", features = ["debug"], rev = "78dfa07"}
gmeta = { git = "https://github.com/gear-tech/gear.git", rev = "78dfa07"}
scale-info = { version = "2", default-features = false, features = ["derive"] }
parity-scale-codec = { version = "3", default-features = false }
```
To describe the metadata interface we use `gmeta` crate:
```
use gmeta::Metadata;
```
We declare the struct for our program `metadata`:
```
pub struct HelloMetadata;
```
and describe its interface. The input for `init` function is a `String`.
```
use gmeta::{InOut, Metadata};
pub struct HelloMetadata;
impl Metadata for HelloMetadata {
pub type Init = InOut<String, ()>;
}
```
The input for the `handle` function is the `InputMessage` enum, and accordingly, the output is `String`. Let's copy the `InputMessage` enum fron the `hello` crate:
```
#[derive(Encode, Decode, TypeInfo, Debug)]
pub enum InputMessage {
SendHelloTo(ActorId),
SendHelloReply,
}
impl Metadata for HelloMetadata {
type Init = InOut<String, ()>;
type Handle = InOut<InputMessage, String>;
...
}
```
Then we define the program state. It is also `String` (It's a set greeting).
```
impl Metadata for HelloMetadata {
type Init = InOut<String, ()>;
type Handle = InOut<InputMessage, String>;
type State = String;
}
```
```Metadata``` has also `Signal`, `Reply` and `Others` types. We don't need them now but still we have to declare them:
```
impl Metadata for HelloMetadata {
type Init = InOut<String, ()>;
type Handle = InOut<InputMessage, String>;
type State = String;
type Reply = ();
type Signal = ();
type Others = ();
}
```
It is possible to read the program state using the state function. Reading State is a free function and does not require gas costs. Let’s define this function in lib.rs file of the hello-world program:
```
#[no_mangle]
extern "C" fn state() {
let state = unsafe {GREETING.as_ref().expect("The contract is not initialized")};
msg::reply(state, 0).expect("Unable to share the state");
}
```
To make it possible to verify metadata for a program, we’ll use the metahash() function:
```
#[no_mangle]
extern "C" fn metahash() {
let metahash: [u8; 32] = include!("../.metahash");
msg::reply(metahash, 0).expect("Unable to share the metahash");
}
```
It’s necessary to add the `hello-world-io` crate to `dependencies` and `build-dependencies` in `Cargo.toml` in the `hello-world` program:
```
[package]
name = "hello-world"
version = "0.1.0"
edition = "2021"
[dependencies]
gstd = { git = "https://github.com/gear-tech/gear.git", features = ["debug"], rev = "78dfa07"}
scale-info = { version = "2", default-features = false, features = ["derive"] }
parity-scale-codec = { version = "3", default-features = false }
hello-world-io = { path = "io"}
[build-dependencies]
gear-wasm-builder = { git = "https://github.com/gear-tech/gear.git", rev = "78dfa07" }
hello-world-io = { path = "io"}
[dev-dependencies]
gtest = { git = "https://github.com/gear-tech/gear.git", rev = "78dfa07"}
```
We also need to change the `build.rs` file using the following code:
```
use hello_world_io::HelloMetadata;
fn main() {
gear_wasm_builder::build_with_metadata::<HelloMetadata>();
}
```
After building the program, a `meta.txt` file will be generated as a result of the smart-contract compilation. This metadata file can be used in UI applications that will interact with this smart contract.
### 4 part
Let's upload our program to the chain.
The easiest way to upload the program is to use the “Upload program” option in the Gear [Idea portal](idea.gear-tech.io).
First, you need to create an account and connect to Gear Idea. Follow the [instructions](https://wiki.gear-tech.io/docs/idea/account/create-account) provided at to create your account.
Once you've logged in, you can select the network on which you want to upload the program by clicking on the gear icon in the lower left corner of the screen. For the Gear Academy workshop, select the workshop node (`wss://node-workshop.gear.rs:443`) and click the "Switch" button.
Select the workshop node and click on the `Switch` button:

Get the test balance clicking on the button in the top right corner:

Then select `Programs` in the left column and click on the Upload program button:

Choose the file `hello_world.opt.wasm` located in the `target/wasm32-unknown-unknown/release` folder:

Then add `meta.txt` file located in the project root:

Enter the name for your program (for example, `Hello_World`) and set the greeting message:

If the program has successfully uploaded, you will see it in the program.

Now you can send messages to your program:

You can also read the program state (Click on `Read full state` button):

It’s our greeting string that was set during the program initialization.
