Hello, World!

This example shows how to create a smart contract in Rust that prints a greeting, without using the eosio crate. This is used to demonstrate the code that is being abstracted away, and to compare the abstraction overhead.

Usage

cleos push action hello hi '["world"]' -p 'hello@active'

Cargo.toml

[package]
name = "hello_bare"
version = "0.1.0"
edition = "2018"
publish = false

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

Source

// Declare the EOSIO externs to read action data and print to the console.
#[cfg(target_arch = "wasm32")]
extern "C" {
    pub fn read_action_data(msg: *mut CVoid, len: u32) -> u32;
    pub fn prints_l(cstr: *const u8, len: u32);
    pub fn printn(name: u64);
}

#[repr(u8)]
pub enum CVoid {
    // Two dummy variants so the #[repr] attribute can be used.
    Variant1,
    Variant2,
}

// EOSIO smart contracts are expected to have an `apply` function.
#[cfg(target_arch = "wasm32")]
#[no_mangle]
pub extern "C" fn apply(_receiver: u64, _code: u64, _action: u64) {
    // First print "Hi, " to the console.
    {
        let msg = "Hi, ";
        let ptr = msg.as_ptr();
        let len = msg.len() as u32;
        unsafe { prints_l(ptr, len) };
    }

    // Read the action data, which is one EOSIO name (a u64, or 8 bytes).
    let name = {
        let mut bytes = [0u8; 8];
        let ptr: *mut CVoid = &mut bytes[..] as *mut _ as *mut CVoid;
        unsafe { read_action_data(ptr, 8) };
        u64::from_le_bytes(bytes)
    };

    // Finally, print the name to the console.
    unsafe { printn(name) };
}

ABI

{
  "version": "eosio::abi/1.0",
  "structs": [
    {
      "name": "hi",
      "base": "",
      "fields": [
        {
          "name": "user",
          "type": "name"
        }
      ]
    }
  ],
  "actions": [
    {
      "name": "hi",
      "type": "hi"
    }
  ]
}