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.