Soroban Rust SDK

repository·main·Indexed 41 days ago

https://github.com/stellar/rs-soroban-sdk

A Rust SDK for developing smart contracts on the Soroban platform within the Stellar network. It provides macros like #[contract] and #[contractimpl], an environment object (Env) for storage and authentication, and tools for building contracts for the wasm32v1-none target using stellar-cli. The SDK includes testutils for simulating the Soroban environment and support for managing ledger state snapshots via LedgerSnapshot.

Tokens
27.6K
Snippets
93
Records
121
Agent score
52%

What's inside Soroban SDK

  1. Build Soroban smart contracts for the Stellar network

    main

    The rs-soroban-sdk is a Rust SDK used to build smart contracts that deploy to the Stellar network and execute within the Soroban runtime.

    For detailed API documentation, use the Rust docs at https://docs.rs/soroban-sdk. For general guidance on building smart contracts, refer to the Stellar Developer Docs.

  2. Define reusable contract interfaces with `#[contracttrait]`

    main

    The #[contracttrait] macro allows you to define reusable smart contract interfaces as Rust traits. When a contract implements such a trait using #[contractimpl(contracttrait)], the macro system automatically generates the necessary machinery for:

    • Specs: Contract specification entries.
    • Exported functions: The actual functions exported in the Wasm file.
    • Client methods: Methods available on the contract client.
    • Args variants: Enum variants for function arguments.
    • Test hooks: Function registration for the test environment.

    A key feature is the handling of default trait functions: if a trait function has a default implementation, it will be exported by the contract unless the implementation explicitly overrides it.

    #[contracttrait]
    trait Pause {
        // Function without a default implementation
        fn f1(&self);
    
        // Function with a default implementation
        fn f2(&self) {
            // default logic
        }
    }
    
    #[contractimpl(contracttrait)]
    impl Pause for Contract {
        // f1 is overridden here
        fn f1(&self) {
            // custom logic
        }
        
        // f2 is NOT overridden, so its default implementation 
        // will be automatically exported as a contract function.
    }
  3. Understand the purpose of test_wasms

    main

    The test_wasms directory contains pre-compiled WebAssembly (.wasm) files used by specific SDK tests. These tests are designed to be sensitive to changes in Wasm content, ensuring that updates to the SDK do not inadvertently alter the generated Wasm bytecode for existing contracts.

    Specifically, test_contract_data.wasm is a compiled version of the tests/contract_data test contract.

  4. Implement a `#[contracttrait]` in a contract

    main

    To use a trait defined with #[contracttrait], apply the #[contractimpl(contracttrait)] attribute to your implementation block. This tells the contractimpl macro to look for the trait's macro (generated during the trait definition) to handle any default functions that you have not explicitly overridden in your impl block.

    #[contractimpl(contracttrait)]
    impl Pause for Contract {
        fn f1(&self) {
            // This overrides the trait's f1
        }
        // Any other functions in the trait with default implementations
        // that are not listed here will be automatically exported.
    }
  5. Use doctest fixtures for documentation examples

    main

    The doctest_fixtures directory contains pre-compiled Wasm contract files used as assets in documentation examples (doctests). If you are writing or studying documentation examples that require a deployed contract, you can reference these files:

    • contract.wasm: A copy of the test_add_u64 test contract.
    • contract_with_constructor.wasm: A copy of the test_constructor test contract.
  6. Build contracts using stellar-cli

    main

    To ensure contracts are compatible with the Soroban runtime, you must build them for the wasm32v1-none target.

    Do not use cargo build to compile contracts. Instead, use the stellar contract build command from the [stellar-cli]. This command automatically targets wasm32v1-none and applies the specific build settings required by the Soroban environment.

    Requirements:

    • Rust Version: 1.84 or newer.
    • stellar-cli Version: As of soroban-sdk v28, you must use stellar-cli v25.2.0 or newer.

    Warning: The wasm32-unknown-unknown target is not supported when using Rust 1.82 or newer. Attempting to build for wasm32-unknown-unknown on these Rust versions will result in a build error because it enables Wasm features (like reference-types and multi-value) that the Soroban environment does not support.

    stellar contract build
  7. Build Soroban smart contracts

    main

    Soroban smart contracts must be built for the wasm32v1-none target. This target is available with Rust 1.84+ and is the only Wasm target supported by the Soroban runtime on Stellar.

    Important: Do not use cargo build to compile contracts. Instead, use the stellar-cli command stellar contract build. This ensures the correct target is used and the necessary build settings for the Soroban runtime are applied.

    Requirements:

    • Rust 1.84+
    • stellar-cli v25.2.0 or newer (required as of soroban-sdk v28).

    Warning: The wasm32-unknown-unknown target is not supported when using Rust 1.82 or newer, as it enables Wasm features (like reference-types and multi-value) that the Soroban environment does not support.

    stellar contract build
  8. Use LedgerSnapshot to manage ledger state snapshots

    main

    LedgerSnapshot is a structure used to store a snapshot of a ledger that can be restored for use in environments as a LedgerInfo and a SnapshotSource. It captures protocol version, sequence number, timestamp, network ID, and various TTL settings, along with a collection of ledger entries.

    Key capabilities include:

    • Creation: Build a snapshot from existing LedgerInfo and a set of entries using from().
    • Persistence: Read from or write to files/readers using JSON serialization.
    • State Management: Update ledger info or replace/update specific entries.
    • Integration: Implements SnapshotSource, allowing it to be used as a source of truth for ledger entries in a host environment.
    ```rust
    // Example of creating a snapshot from info and entries
    let snapshot = LedgerSnapshot::from(ledger_info, entries_iterator);
    
    // Writing the snapshot to a file
    snapshot.write_file("snapshot.json")?;
    
    // Reading a snapshot from a file
    let loaded_snapshot = LedgerSnapshot::read_file("snapshot.json")?;
    ```埋
  9. Convert values using `Val`, `FromVal`, and `IntoVal`

    main

    Soroban uses the Val type as the raw value representation of the smart contract platform. To move data between Rust types and the Soroban environment, use the following traits:

    • Val: The raw value type used for storage and passing between contracts.
    • FromVal: Used to convert from a Val to a Rust type.
    • IntoVal: Used to convert from a Rust type to a Val.
    • TryFromVal / TryIntoVal: Variants for conversions that may fail.
  10. Use the generated Client to call contract functions

    main

    When you use the client derivation macro, it generates a Client struct for your contract. This client provides two versions of every exported contract function:

    1. function_name(...): A standard invocation that returns the result directly. It uses env.invoke_contract under the hood.
    2. try_function_name(...): A fallible version that returns a Result. It uses env.try_invoke_contract under the hood.

    Note that functions starting with __ are reserved for callbacks and hooks and are not exported by the client. The client automatically handles argument conversion using the IntoVal trait.

  11. Use the Vec collection type

    main

    A Vec<T> is a sequential, indexable, and growable collection. Values are stored in the Soroban environment and are converted to and from Val types during transmission.

    Key Behaviors

    • Type Safety: Values in a Vec are not guaranteed to be of type T at the environment level. If you receive a Vec from an external contract call, use try_ prefixed methods to safely handle potential conversion errors.
    • Error Handling:
      • Methods prefixed with try_ return a Result and are resilient to conversion failures.
      • Methods without the try_ prefix will panic if conversion fails or if an index is out-of-bounds.
      • Methods with the _unchecked suffix will panic if called with out-of-bounds indexes.
    • Binary Data: For storing u8s or raw binary data, use Bytes or BytesN instead of Vec<u8> for better efficiency.
  12. Implement SnapshotSource with LedgerSnapshot

    main

    LedgerSnapshot implements the SnapshotSource trait. This allows a LedgerSnapshot (or a reference to one) to be used in environments that require a source for ledger entries.

    When calling get(key), the snapshot searches its internal ledger_entries for the matching LedgerKey. If found, it returns Ok(Some((LedgerEntry, Option<u32>))); otherwise, it returns Ok(None).