Rust

Dependencies

Our Rust SDK consist of two crates. rust-sdk and rust-sdk-macros.

To create a QAN contract initialize a standard rust project as follows:

cargo init --lib mycontract

Next, import the necessary crates in Cargo.toml:

[package]
name = "mycontract"
version = "0.1.0"
authors = ["Nyan <nyan@nyan.cat>"]
edition = "2018"

[lib]
crate-type = ["cdylib"]

[dependencies]
qansdk-macros = "0.1.0"
qansdk = "0.1.0"
serde = {version = "1.0.114", default-features = false, features = ["derive"] }
wasm-bindgen = "0.2.64"
serde_cbor = {version = "0.11.1", default-features = false}

Coding and building contracts

With the dependencies in place, we are ready to edit src/lib.rs!

QAN smart contracts support almost the whole of rust_std! This means you don't need annotators, decorators, macros etc and every rust code with a (non-mangled) main is a valid smart contract!

The only trick you need to keep in mind is that to get parameters passed to the VM by the incomming transaction, you need to call get_param("paramname"). Rust can infer the type by default but it always nice if you help it out :)

To store and get a value on chain (into/from the account) use sstore and sload respectively like a simple key-value map.

use std::string::String; // we can use std!

pub fn hello(name: String) -> String {
    format!("hello {}", name)
}
pub fn add(a: i32, b: i32) -> i32 {
	a + b
}

#[no_mangle]
pub unsafe fn main() -> i32 {
    let p: i32 = get_arg("number");
    let caller: String = get_arg("caller_name");

    sstore("answer", p+1);
    sstore("greeting", hello(caller));
    return 0;
}

Let's build the contract with cargo build --release --target=wasm32-unknown-unknown

If you dont have the WASM target, use the following command to install it:

rustup target add wasm32-unknown-unknown

Deployment

With your contract binary ready at target/wasm32-unknown-unknown/release/mycontract.wasm let's deploy it into the network!

Fire up wallet_cli and unlock our wallet with the password:

 _________
< welcome >
 ---------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||
Please enter a wallet path.
If it doesn't exist I'll create it for you
Wallet: /tmp/mywallet
Enter wallet key:*********
>

After that use the deploy command with the binary path to send it as a transaction to the 0x00000..00 contract:

>deploy /home/nyan/mycontract/target/wasm32-unknown-unknown/release/mycontract.wasm
transaction_hash: 84aa5a3db0ea2ba66eb84ac3df0e3124bce087d8
contract_hash: 5269a904e785bbc4a32fa59aea09a92a902d8434

The two return hashes indicate the transaction made it into the mempool and we are now waiting for it to be confirmed.

The resulting contract address (contract_hash above) is not calculated from the contract bytecode but from the sender address and it's nonce.