Loam SDK

A Software Development Kit (SDK) and build tool for writing smart contracts in Rust on Wasm blockchains.

Currently, the focus is on the Soroban VM, but the same ideas apply to other VMs.

Table of Contents

Getting Started

Installation

To install just, run the following command:

bash cargo install just

Setup

To set up the environment, run:

bash just setup

Redeploy

To see redeployment in action, use:

bash just redeploy

Contract Riffs

A contract riff (or mixin) is a type that implements the IntoKey trait, which is used for lazily loading and storing the type.

Creating Contract Riffs

Here's an example of how to create a contract riff:

```rust

[contracttype]

[derive(IntoKey)]

pub struct Messages(Map); ```

This generates the following implementation:

rust impl IntoKey for Messages { type Key = IntoVal<Env, RawVal>; fn into_key() -> Self::Key { String::from_slice("messages") }

External API

You can also create and implement external APIs for contract riffs:

```rust

[riff]

pub trait IsPostable { fn messagesget(&self, author: Address) -> Option; fn messagesset(&mut self, author: Address, text: String); } ```

CoreRiff

The CoreRiff trait provides the minimum logic needed for a contract to be redeployable. A contract should be able to be redeployed to another contract that can also be redeployed. Redeployment requires ownership, as it would be undesirable for an account to redeploy the contract without permission.

Using the CoreRiff

To use the core riff, create a Contract structure and implement the CoreRiff for it. The Contract will be redeployable and will be able to implement other Riffs.

```rust use loamsdk::{sorobancontract, sorobansdk}; use loamsdkcoreriff::{owner::Owner, CoreRiff};

pub struct Contract;

impl CoreRiff for Contract { type Impl = Owner; }

soroban_contract!(); ```

This code generates the following implementation:

```rust struct SorobanContract;

[contractimpl]

impl SorobanContract { pub fn ownerset(env: Env, owner: Address) { setenv(env); Contract::ownerset(owner); } pub fn ownerget(env: Env) -> Option

{ setenv(env); Contract::ownerget() } pub fn redeploy(env: Env, wasmhash: BytesN<32>) { setenv(env); Contract::redeploy(wasm_hash); } // Riff methods would be inserted here. // Contract must implement all Riffs and is the proxy for the contract calls. // This is because the Riffs have default implementations which call the associated type } ```

By specifying the associated Impl type for CoreRiff, you enable the default Owner methods to be used (owner_set, owner_get, redeploy). However, you can also provide a different implementation if needed by replacing Owner with a different struct/enum that also implements IsCoreRiff.

Notice that the generated code calls Contract::redeploy and other methods. This ensures that the Contract type is redeployable, while also allowing for extensions, as Contract can overwrite the default methods.