stellar/stellar-docs/smart-contracts

Claude Code and agent skill by stellar/stellar-docs

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Stellar smart contract development (Rust, soroban-sdk). Entry point with project setup, contract anatomy, and build/deploy workflow, routing to three companion files in this directory — development.md (storage, auth, cross-contract calls, events, errors, upgrades, factories, troubleshooting), testing.md (unit, fuzz, property, fork, mutation, integration), and security.md (vulnerability classes, checklists, tooling, audits). Use when writing, testing, securing, or shipping Stellar smart contract…

Install

npx vskill@latest install stellar/stellar-docs/smart-contracts

SKILL.md

Stellar Smart Contracts

Guide for building Stellar smart contracts in Rust. Smart contracts on Stellar were formerly branded "Soroban" — the platform name is retired, but the Rust SDK (soroban-sdk) and several tool names keep the prefix.

This file covers setup and the core workflow. The deep dives are included below — jump to the section that matches the task:

TaskSection
Storage, auth, cross-contract calls, events, errors, upgrades, factories, troubleshootingDevelopment Patterns
Unit, integration, fuzz, property, fork, and mutation testingTesting
Security review, vulnerability classes, checklists, audit prep, toolingSecurity

When to use this skill

  • Writing a Stellar smart contract in Rust
  • Setting up contract tests (any layer)
  • Reviewing a contract for security issues
  • Architecting upgradeable contracts, factories, governance, or DeFi primitives
  • Debugging a contract-specific error (auth, storage, archival, resource limits)

Related skills

  • Assets, trustlines, and SAC bridge → /.well-known/agent-skills/assets/skill.md
  • Frontend/wallets that call your contract → /.well-known/agent-skills/dapp/skill.md
  • Chain data queries (RPC/Horizon) → /.well-known/agent-skills/data/skill.md
  • ZK verification (BLS12-381, Groth16, Circom/Noir/RISC Zero) → /.well-known/agent-skills/zk-proofs/skill.md
  • SEP/CAP standards and ecosystem links → /.well-known/agent-skills/standards/skill.md

Platform constraints

Contracts are Rust compiled to WebAssembly, run in a sandboxed host:

  • #![no_std] required — use soroban_sdk types (String, Vec, Map, Symbol), not the Rust standard library
  • 64KB compiled contract size limit — use the release profile below
  • Symbol is limited to 32 characters; symbol_short!() covers up to 9
  • Storage is rented: every entry has a TTL and can be archived — see development.md
  • No delegatecall, no classical cross-contract reentrancy — see security.md

Project setup

bash
stellar contract init my-contract # scaffolds a Cargo workspace with contracts/
cd my-contract

Cargo.toml essentials:

toml
[lib]
crate-type = ["cdylib"]
[dependencies]
soroban-sdk = "25.0.1" # check https://crates.io/crates/soroban-sdk for latest
[dev-dependencies]
soroban-sdk = { version = "25.0.1", features = ["testutils"] } # match above
[profile.release]
opt-level = "z"
overflow-checks = true
debug = 0
strip = "symbols"
debug-assertions = false
panic = "abort"
codegen-units = 1
lto = true

Contract anatomy

One compact example showing state, constructor, auth, TTL, and a typed error:

rust
#![no_std]
use soroban_sdk::{contract, contracterror, contractimpl, contracttype, Address, Env};
#[contracttype]
#[derive(Clone)]
pub enum DataKey {
Admin,
Counter,
}
#[contracterror]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[repr(u32)]
pub enum Error {
NotInitialized = 1,
}
#[contract]
pub struct CounterContract;
#[contractimpl]
impl CounterContract {
// Runs once, atomically, at deploy time (Protocol 22+). Must be named
// `__constructor` and return (). Does not run again on upgrade.
pub fn __constructor(env: Env, admin: Address) {
env.storage().instance().set(&DataKey::Admin, &admin);
env.storage().instance().set(&DataKey::Counter, &0u32);
}
pub fn increment(env: Env) -> Result<u32, Error> {
let admin: Address = env
.storage()
.instance()
.get(&DataKey::Admin)
.ok_or(Error::NotInitialized)?;
admin.require_auth();
let count: u32 = env.storage().instance().get(&DataKey::Counter).unwrap_or(0);
let count = count + 1;
env.storage().instance().set(&DataKey::Counter, &count);
// Extend TTL so contract state is not archived (threshold, extend-to)
env.storage().instance().extend_ttl(100, 518400);
Ok(count)
}
pub fn get_count(env: Env) -> u32 {
env.storage().instance().get(&DataKey::Counter).unwrap_or(0)
}
}

Full patterns (three storage types, auth variants, cross-contract calls, events, custom types): development.md.

Build, deploy, invoke

bash
# Build optimized WASM → target/wasm32-unknown-unknown/release/*.wasm
stellar contract build
# Create and fund an identity (testnet)
stellar keys generate --global alice --network testnet --fund
# Deploy (constructor args go after the `--`)
stellar contract deploy \
--wasm target/wasm32-unknown-unknown/release/my_contract.wasm \
--source alice \
--network testnet \
-- \
--admin alice
# Invoke
stellar contract invoke \
--id CONTRACT_ID \
--source alice \
--network testnet \
-- \
increment

To upload WASM without instantiating (e.g. for factories or upgrades), use stellar contract upload (the older stellar contract install is a deprecated alias).

Minimal test

rust
#![cfg(test)]
use super::*;
use soroban_sdk::{testutils::Address as _, Address, Env};
#[test]
fn test_increment() {
let env = Env::default();
env.mock_all_auths();
let admin = Address::generate(&env);
let contract_id = env.register(CounterContract, (admin.clone(),));
let client = CounterContractClient::new(&env, &contract_id);
assert_eq!(client.increment(), 1);
assert_eq!(client.get_count(), 1);
}

Auth mocking, fuzzing, fork tests, and CI setup: testing.md.

Before mainnet

Work through the checklists in security.md — authorization, reinitialization, arithmetic, storage TTLs, and cross-contract validation are the recurring failure modes.

Documentation


Development Patterns

Core and advanced patterns for Stellar smart contracts. For setup and the basic workflow, start at SKILL.md; for tests see testing.md; for security review see security.md.

Architecture

Contracts run as WebAssembly guests in a sandboxed host. The host provides storage, crypto, and cross-contract calls; guest code references host objects via handles, not direct memory. Practical consequences:

  • #![no_std] — use soroban_sdk collections and strings
  • 64KB compiled size limit (see Contract size below)
  • Rust is the supported language. Community alternatives (AssemblyScript, Solidity via Solang) exist but are not production-ready — see migration docs.

Storage

Three storage types with different costs and lifetimes. Choosing wrong is a top source of bugs and fee waste:

TypeLifetimeUse for
instance()Tied to the contract instance, shared TTLAdmin address, global config, small global state
persistent()Per-key TTL, archived when expired but restorableUser balances, anything that must survive
temporary()Per-key TTL, deleted when expired, not restorableCaches, session data, short-lived flags
rust
env.storage().instance().set(&DataKey::Admin, &admin);
env.storage().persistent().set(&DataKey::Balance(user), &balance);
env.storage().temporary().set(&DataKey::Cache(key), &value);
TTL management

Every entry has a TTL (in ledgers, ~5s each) and is archived when it expires. Extend proactively in functions that touch the data:

rust
const MIN_TTL: u32 = 17280; // ~1 day
const EXTEND_TO: u32 = 518400; // ~30 days
// extend_ttl(threshold, extend_to): only extends if TTL < threshold
env.storage().instance().extend_ttl(MIN_TTL, EXTEND_TO);
env.storage().persistent().extend_ttl(&DataKey::Balance(user), MIN_TTL, EXTEND_TO);

Archived persistent entries can be restored with a RestoreFootprint operation, but that costs an extra transaction — design TTL extension into hot paths instead. Details: state archival docs.

Typed storage keys

Always use a #[contracttype] enum for keys — ad-hoc symbols invite collisions:

rust
#[contracttype]
#[derive(Clone)]
pub enum DataKey {
Admin,
Balance(Address),
Allowance(Address, Address), // (owner, spender)
}

Data types

rust
use soroban_sdk::{Address, Bytes, BytesN, Map, String, Symbol, Vec};
let addr: Address = env.current_contract_address();
let sym: Symbol = symbol_short!("transfer"); // ≤9 chars; Symbol max is 32
let s: String = String::from_str(&env, "hello");
let hash: BytesN<32> = env.crypto().sha256(&bytes).into();
let v: Vec<u32> = vec![&env, 1, 2, 3];
let m: Map<Symbol, u32> = Map::new(&env);

Custom types derive #[contracttype]:

rust
#[contracttype]
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct TokenMetadata {
pub name: String,
pub symbol: Symbol,
pub decimals: u32,
}

Authorization

Authorization is opt-in and explicit. Call require_auth() on every address whose consent the operation needs:

rust
pub fn transfer(env: Env, from: Address, to: Address, amount: i128) {
from.require_auth();
// or bind the auth to specific arguments:
// from.require_auth_for_args((&to, amount).into_val(&env));
// ...
}

Admin pattern:

rust
fn require_admin(env: &Env) {
let admin: Address = env.storage().instance().get(&DataKey::Admin).unwrap();
admin.require_auth();
}

Authorization semantics (sub-invocations, custom accounts): auth docs.

Constructors

__constructor runs once, atomically, at deploy time (Protocol 22+). Prefer it over a separate initialize function — it removes the front-running window between deploy and init:

rust
pub fn __constructor(env: Env, admin: Address, initial_value: u32) {
env.storage().instance().set(&DataKey::Admin, &admin);
env.storage().instance().set(&DataKey::Value, &initial_value);
}

Rules: exact name __constructor, returns (), runs only at creation (not on upgrade), failure aborts the deployment atomically. Pass args at deploy time after the -- separator (see SKILL.md).

If you must support a guarded initialize instead (pre-Protocol-22 targets), check-and-set an Initialized flag — see security.md.

Cross-contract calls

Import another contract's WASM to get a typed client:

rust
mod token_contract {
soroban_sdk::contractimport!(
file = "../token/target/wasm32-unknown-unknown/release/token.wasm"
);
}
pub fn deposit(env: Env, user: Address, token: Address, amount: i128) {
user.require_auth();
let token_client = token_contract::Client::new(&env, &token);
token_client.transfer(&user, &env.current_contract_address(), &amount);
}

For Stellar assets, use the built-in SAC client — every asset has a Stellar Asset Contract:

rust
use soroban_sdk::token::Client as TokenClient;
let token = TokenClient::new(&env, &asset_contract_id);
token.transfer(&from, &to, &amount);

SAC details and asset interop: /.well-known/agent-skills/assets/skill.md. Validate addresses you call — see security.md.

Events

rust
use soroban_sdk::contractevent;
#[contractevent(topics = ["transfer"])]
pub struct TransferEvent {
pub from: Address,
pub to: Address,
pub amount: i128,
}
// in a contract function:
TransferEvent { from, to, amount }.publish(&env);

Emit events for every state change you'll want to index or audit — events are much cheaper than storing queryable state.

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
146
Repository forks
325
7-day trend score
0

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/stellar/stellar-docs/smart-contracts/badge)](https://verified-skill.com/skills/stellar/stellar-docs/smart-contracts)

Something wrong with this skill or its page? Tell us.