rs-soroban-sdk

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Soroban SDK Skill

Soroban SDK 技能指南

Soroban SDK is the Rust SDK for building smart contracts on the Stellar blockchain's Wasm-powered Soroban runtime.
Soroban SDK 是用于在Stellar区块链的Wasm驱动Soroban运行时上构建智能合约的Rust SDK。

Prerequisites

前置要求

  • Rust: v1.84.0 or higher
  • Target: Install with
    rustup target add wasm32v1-none
  • Stellar CLI: v25.1.0+ (recommended for building and testing)
    • Install:
      curl -fsSL https://github.com/stellar/stellar-cli/raw/main/install.sh | sh
    • Or:
      brew install stellar-cli
  • Rust:v1.84.0 或更高版本
  • Target:通过
    rustup target add wasm32v1-none
    安装
  • Stellar CLI:v25.1.0+(推荐用于构建和测试)
    • 安装方式:
      curl -fsSL https://github.com/stellar/stellar-cli/raw/main/install.sh | sh
    • 或:
      brew install stellar-cli

⚠️ Security First

⚠️ 安全优先

Smart contracts handle valuable assets. Follow these rules to prevent vulnerabilities:
Do:
  • ✅ Call
    require_auth()
    before any state changes
  • ✅ Validate all inputs (amounts, addresses, array lengths)
  • ✅ Use checked arithmetic (
    .checked_add()
    ,
    .checked_mul()
    )
  • ✅ Extend TTL on all persistent/instance storage writes
  • ✅ Initialize contract only once with a guard flag
  • ✅ Test authorization, overflow, and edge cases
Don't:
  • ❌ Skip authorization checks
  • ❌ Use unchecked arithmetic (can overflow/underflow)
  • ❌ Allow reinitialization
  • ❌ Forget to extend TTL on storage writes
  • ❌ Trust external addresses without validation
See references/security.md for complete security guidance.
智能合约会处理高价值资产,请遵循以下规则以预防漏洞:
需要做到:
  • ✅ 在任何状态变更之前调用
    require_auth()
  • ✅ 验证所有输入(金额、地址、数组长度)
  • ✅ 使用带检查的算术运算(
    .checked_add()
    .checked_mul()
  • ✅ 在所有Persistent/Instance存储写入操作时延长TTL
  • ✅ 使用防护标志确保合约仅初始化一次
  • ✅ 测试授权、溢出和边缘场景
切勿:
  • ❌ 跳过授权检查
  • ❌ 使用无检查的算术运算(可能导致溢出/下溢)
  • ❌ 允许重初始化
  • ❌ 忘记在存储写入时延长TTL
  • ❌ 未验证就信任外部地址
完整的安全指南请参考references/security.md

Core Contract Structure

核心合约结构

Every Soroban contract follows this pattern:
rust
#![no_std]  // Required: excludes Rust std library (too large for contracts)

use soroban_sdk::{contract, contractimpl, Env};

#[contract]
pub struct MyContract;

#[contractimpl]
impl MyContract {
    pub fn function_name(env: Env, param: Type) -> ReturnType {
        // Implementation
    }
}
Key requirements:
  • #![no_std]
    - Must be first line (standard library not available)
  • All contracts export as a single contract when compiled to WASM
  • Function names max 32 characters
  • Contract inputs must not be references
Key attributes:
  • #[contract]
    - Marks the struct as a contract type
  • #[contractimpl]
    - Exports public functions as contract functions
  • #[contracttype]
    - Converts custom types to/from
    Val
    for storage
  • #[contracterror]
    - Defines error enums with
    repr(u32)
  • #[contractevent]
    - Marks structs as publishable events
所有Soroban合约均遵循以下模式:
rust
#![no_std]  // Required: excludes Rust std library (too large for contracts)

use soroban_sdk::{contract, contractimpl, Env};

#[contract]
pub struct MyContract;

#[contractimpl]
impl MyContract {
    pub fn function_name(env: Env, param: Type) -> ReturnType {
        // Implementation
    }
}
核心要求:
  • #![no_std]
    - 必须作为第一行(标准库不可用)
  • 所有合约编译为WASM后会导出为单个合约
  • 函数名最长32个字符
  • 合约输入不能是引用类型
核心属性:
  • #[contract]
    - 将结构体标记为合约类型
  • #[contractimpl]
    - 将公共函数导出为合约函数
  • #[contracttype]
    - 将自定义类型与
    Val
    相互转换以用于存储
  • #[contracterror]
    - 定义带有
    repr(u32)
    的错误枚举
  • #[contractevent]
    - 将结构体标记为可发布的事件

Environment (Env)

执行环境(Env)

The
Env
type provides access to the contract execution environment. It's always the first parameter in contract functions.
rust
pub fn my_function(env: Env) {
    // Access storage
    env.storage().persistent();
    env.storage().temporary();
    env.storage().instance();

    // Get contract address
    let contract_id = env.current_contract_address();

    // Get ledger info
    let ledger = env.ledger().sequence();
    let timestamp = env.ledger().timestamp();
}
Env
类型提供对合约执行环境的访问权限,它始终是合约函数的第一个参数。
rust
pub fn my_function(env: Env) {
    // Access storage
    env.storage().persistent();
    env.storage().temporary();
    env.storage().instance();

    // Get contract address
    let contract_id = env.current_contract_address();

    // Get ledger info
    let ledger = env.ledger().sequence();
    let timestamp = env.ledger().timestamp();
}

Storage Types

存储类型

Soroban provides three storage types with different lifetimes and costs. See references/storage.md for detailed patterns.
Quick reference:
  • Persistent
    - Long-lived data (user balances, state)
  • Temporary
    - Short-lived data (caching, temporary locks)
  • Instance
    - Contract-wide configuration/metadata
Soroban提供三种具有不同生命周期和成本的存储类型。详细的实现模式请参考references/storage.md
速查:
  • Persistent
    - 长期存储数据(用户余额、状态)
  • Temporary
    - 短期存储数据(缓存、临时锁)
  • Instance
    - 合约级配置/元数据

Data Types

数据类型

Core Types

核心类型

  • Address
    - Universal identifier (contracts or accounts)
  • Symbol
    - Short strings with limited charset (max 32 chars)
  • Vec<T>
    - Growable array type
  • Map<K, V>
    - Ordered key-value dictionary
  • Bytes
    - Growable byte array
  • BytesN<N>
    - Fixed-size byte array
  • String
    - UTF-8 string type
  • U256
    ,
    I256
    - 256-bit integers
  • Address
    - 通用标识符(合约或账户)
  • Symbol
    - 字符集受限的短字符串(最多32个字符)
  • Vec<T>
    - 可增长数组类型
  • Map<K, V>
    - 有序键值字典
  • Bytes
    - 可增长字节数组
  • BytesN<N>
    - 固定大小字节数组
  • String
    - UTF-8字符串类型
  • U256
    ,
    I256
    - 256位整数

Type Macros

类型宏

  • vec![&env, item1, item2]
    - Create Vec
  • map![&env, (key1, val1), (key2, val2)]
    - Create Map
  • symbol_short!("text")
    - Create Symbol constant
  • bytes!(&env, 0x010203)
    - Create Bytes
  • bytesn!(&env, 0x010203)
    - Create BytesN
  • vec![&env, item1, item2]
    - 创建Vec
  • map![&env, (key1, val1), (key2, val2)]
    - 创建Map
  • symbol_short!("text")
    - 创建Symbol常量
  • bytes!(&env, 0x010203)
    - 创建Bytes
  • bytesn!(&env, 0x010203)
    - 创建BytesN

Authorization

授权机制

⚠️ Critical: Authorization vulnerabilities are the #1 cause of smart contract exploits. Always call
require_auth()
before any state changes.
When a function requires authorization, use
Address::require_auth()
:
rust
pub fn transfer(env: Env, from: Address, to: Address, amount: i128) {
    from.require_auth();  // ✅ ALWAYS FIRST
    // Now authorized to proceed
}
Common mistake: Authorizing the wrong address
rust
// ❌ WRONG: Authorizing recipient
pub fn transfer(env: Env, from: Address, to: Address, amount: i128) {
    to.require_auth();  // Anyone can receive!
}

// ✅ CORRECT: Authorize sender
pub fn transfer(env: Env, from: Address, to: Address, amount: i128) {
    from.require_auth();  // Sender must approve
}
For custom auth logic, see references/auth.md.
⚠️ 关键提示:授权漏洞是智能合约被攻击的首要原因。请始终在任何状态变更之前调用
require_auth()
当函数需要授权时,使用
Address::require_auth()
rust
pub fn transfer(env: Env, from: Address, to: Address, amount: i128) {
    from.require_auth();  // ✅ ALWAYS FIRST
    // Now authorized to proceed
}
常见错误:授权错误的地址
rust
// ❌ WRONG: Authorizing recipient
pub fn transfer(env: Env, from: Address, to: Address, amount: i128) {
    to.require_auth();  // Anyone can receive!
}

// ✅ CORRECT: Authorize sender
pub fn transfer(env: Env, from: Address, to: Address, amount: i128) {
    from.require_auth();  // Sender must approve
}
自定义授权逻辑请参考references/auth.md

Testing

测试

Use
testutils
feature for testing. Tests use
Env::default()
and register contracts:
rust
#[test]
fn test() {
    let env = Env::default();
    let contract_id = env.register(MyContract, ());
    let client = MyContractClient::new(&env, &contract_id);

    let result = client.my_function(&param);
    assert_eq!(result, expected);
}
For advanced testing patterns, see references/testing.md.
使用
testutils
特性进行测试。测试使用
Env::default()
并注册合约:
rust
#[test]
fn test() {
    let env = Env::default();
    let contract_id = env.register(MyContract, ());
    let client = MyContractClient::new(&env, &contract_id);

    let result = client.my_function(&param);
    assert_eq!(result, expected);
}
高级测试模式请参考references/testing.md

Tokens

代币处理

Work with tokens using the
token
module:
rust
use soroban_sdk::token::{TokenClient, StellarAssetClient};

pub fn use_token(env: Env, token_address: Address, amount: i128) {
    let token = TokenClient::new(&env, &token_address);
    token.transfer(&from, &to, &amount);
}
See references/tokens.md for token integration patterns.
使用
token
模块处理代币:
rust
use soroban_sdk::token::{TokenClient, StellarAssetClient};

pub fn use_token(env: Env, token_address: Address, amount: i128) {
    let token = TokenClient::new(&env, &token_address);
    token.transfer(&from, &to, &amount);
}
代币集成模式请参考references/tokens.md

Events and Logging

事件与日志

Publish events for off-chain tracking:
rust
env.events().publish((symbol_short!("transfer"), from, to), amount);
During development, use logging:
rust
use soroban_sdk::log;
log!(&env, "Debug message: {}", value);
发布事件以用于链下追踪:
rust
env.events().publish((symbol_short!("transfer"), from, to), amount);
开发过程中可使用日志功能:
rust
use soroban_sdk::log;
log!(&env, "Debug message: {}", value);

Error Handling

错误处理

Define custom errors with
#[contracterror]
:
rust
#[contracterror]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum Error {
    InvalidAmount = 1,
    Unauthorized = 2,
    InsufficientBalance = 3,
}
Use with
panic_with_error!
or
assert_with_error!
:
rust
// Validate before operations
assert_with_error!(&env, amount > 0, Error::InvalidAmount);
assert_with_error!(&env, balance >= amount, Error::InsufficientBalance);

// Or panic directly
if amount == 0 {
    panic_with_error!(&env, Error::InvalidAmount);
}
⚠️ Security: Always validate inputs to prevent:
  • Integer overflow/underflow (use checked arithmetic)
  • Invalid addresses or amounts
  • Array length mismatches
  • Division by zero
使用
#[contracterror]
定义自定义错误:
rust
#[contracterror]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum Error {
    InvalidAmount = 1,
    Unauthorized = 2,
    InsufficientBalance = 3,
}
结合
panic_with_error!
assert_with_error!
使用:
rust
// Validate before operations
assert_with_error!(&env, amount > 0, Error::InvalidAmount);
assert_with_error!(&env, balance >= amount, Error::InsufficientBalance);

// Or panic directly
if amount == 0 {
    panic_with_error!(&env, Error::InvalidAmount);
}
⚠️ 安全提示:请始终验证输入以预防:
  • 整数溢出/下溢(使用带检查的算术运算)
  • 无效地址或金额
  • 数组长度不匹配
  • 除零错误

Deployment

合约部署

Contracts can deploy other contracts:
rust
use soroban_sdk::deploy::{Deployer, ContractIdPreimage};

let deployer = env.deployer();
let contract_id = deployer.deploy_wasm(&wasm_hash, &salt);
合约可以部署其他合约:
rust
use soroban_sdk::deploy::{Deployer, ContractIdPreimage};

let deployer = env.deployer();
let contract_id = deployer.deploy_wasm(&wasm_hash, &salt);

Common Patterns

常见实现模式

State Management

状态管理

Store contract state in Instance storage for contract-wide config:
rust
const STATE_KEY: Symbol = symbol_short!("STATE");

pub fn init(env: Env, admin: Address) {
    env.storage().instance().set(&STATE_KEY, &admin);
}

pub fn get_admin(env: Env) -> Address {
    env.storage().instance().get(&STATE_KEY).unwrap()
}
将合约状态存储在Instance存储中以用于合约级配置:
rust
const STATE_KEY: Symbol = symbol_short!("STATE");

pub fn init(env: Env, admin: Address) {
    env.storage().instance().set(&STATE_KEY, &admin);
}

pub fn get_admin(env: Env) -> Address {
    env.storage().instance().get(&STATE_KEY).unwrap()
}

Iterating Over Collections

集合遍历

Use iterator methods on Vec and Map:
rust
let total: i128 = amounts
    .iter()
    .map(|x| x.unwrap())
    .sum();
对Vec和Map使用迭代器方法:
rust
let total: i128 = amounts
    .iter()
    .map(|x| x.unwrap())
    .sum();

Cross-Contract Calls

跨合约调用

Import contracts with
contractimport!
or create manual clients:
rust
let other_contract = OtherContractClient::new(&env, &contract_address);
let result = other_contract.function(&args);
使用
contractimport!
导入合约或手动创建客户端:
rust
let other_contract = OtherContractClient::new(&env, &contract_address);
let result = other_contract.function(&args);

Project Setup

项目配置

Requirements

要求

  • Rust toolchain v1.84.0 or higher (required for
    wasm32v1-none
    target)
  • Stellar CLI v25.1.0 or higher
  • Install target:
    rustup target add wasm32v1-none
  • Rust工具链v1.84.0或更高版本
    wasm32v1-none
    目标所需)
  • Stellar CLI v25.1.0或更高版本
  • 安装目标:
    rustup target add wasm32v1-none

Cargo.toml Configuration

Cargo.toml配置

Workspace-level Cargo.toml:
toml
[workspace]
resolver = "2"
members = ["contracts/*"]

[workspace.dependencies]
soroban-sdk = "25"

[profile.release]
opt-level = "z"
overflow-checks = true
debug = 0
strip = "symbols"
debug-assertions = false
panic = "abort"
codegen-units = 1
lto = true

[profile.release-with-logs]
inherits = "release"
debug-assertions = true
Contract-level Cargo.toml:
toml
[package]
name = "my-contract"
version = "0.0.0"
edition = "2021"

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

[dependencies]
soroban-sdk = { workspace = true }

[dev-dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }
工作区级别的Cargo.toml:
toml
[workspace]
resolver = "2"
members = ["contracts/*"]

[workspace.dependencies]
soroban-sdk = "25"

[profile.release]
opt-level = "z"
overflow-checks = true
debug = 0
strip = "symbols"
debug-assertions = false
panic = "abort"
codegen-units = 1
lto = true

[profile.release-with-logs]
inherits = "release"
debug-assertions = true
合约级别的Cargo.toml:
toml
[package]
name = "my-contract"
version = "0.0.0"
edition = "2021"

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

[dependencies]
soroban-sdk = { workspace = true }

[dev-dependencies]
soroban-sdk = { workspace = true, features = ["testutils"] }

Building Contracts

构建合约

Recommended: Use Stellar CLI (automatically sets correct target and profile):
bash
stellar contract build
Equivalent manual command:
bash
cargo build --target wasm32v1-none --release
Output:
target/wasm32v1-none/release/contract_name.wasm
Optimize for production:
bash
stellar contract optimize --wasm target/wasm32v1-none/release/contract_name.wasm
Produces:
contract_name.optimized.wasm
推荐方式:使用Stellar CLI(自动设置正确的目标和配置文件):
bash
stellar contract build
等效手动命令
bash
cargo build --target wasm32v1-none --release
输出文件:
target/wasm32v1-none/release/contract_name.wasm
生产环境优化
bash
stellar contract optimize --wasm target/wasm32v1-none/release/contract_name.wasm
生成文件:
contract_name.optimized.wasm

Additional Resources

额外资源

For detailed information on specific topics, see:
  • Storage patterns and TTL management
  • Authorization and auth context
  • Testing strategies and utilities
  • Token integration and Stellar Asset Contracts
  • Common contract patterns and examples
  • Security best practices and vulnerabilities ⚠️ CRITICAL
如需特定主题的详细信息,请参考:
  • 存储模式与TTL管理
  • 授权机制与认证上下文
  • 测试策略与工具
  • 代币集成与Stellar Asset Contracts
  • 常见合约模式与示例
  • 安全最佳实践与漏洞预防 ⚠️ 至关重要

Security Quick Reference

安全速查指南

Critical rules to prevent vulnerabilities:
  1. Always authorize first: Call
    require_auth()
    before any state changes
  2. Validate all inputs: Check amounts, addresses, array lengths
  3. Prevent overflow: Use checked arithmetic for all math operations
  4. Initialize once: Use initialization flag to prevent reinitialization
  5. Extend TTL: Always extend TTL on persistent/instance storage writes
  6. Choose storage wisely: Persistent for critical data, Temporary for cache
  7. Test thoroughly: Cover authorization, overflows, edge cases
See references/security.md for complete security guidance.
预防漏洞的关键规则:
  1. 始终先授权:在任何状态变更之前调用
    require_auth()
  2. 验证所有输入:检查金额、地址、数组长度
  3. 预防溢出:所有数学运算使用带检查的算术
  4. 仅初始化一次:使用初始化标志防止重初始化
  5. 延长TTL:在Persistent/Instance存储写入时始终延长TTL
  6. 合理选择存储类型:Persistent用于关键数据,Temporary用于缓存
  7. 全面测试:覆盖授权、溢出、边缘场景
完整的安全指南请参考references/security.md