assets
Stellar Assets (classic) + trustlines + Stellar Asset Contract (SAC) bridge to Soroban. Covers asset issuance, distribution, authorization flags, clawback, regulated assets, trustline management, and the SAC interop layer that exposes classic assets as Soroban tokens. Use when tokenizing real-world assets, issuing stablecoins, managing trustlines, or bridging classic assets to Soroban contracts.
What this skill does
# Stellar Assets, Trustlines, and SAC
Stellar's native token mechanism: classic asset issuance, trustlines, and the Stellar Asset Contract (SAC) bridge that makes classic assets usable from Soroban. Default to classic assets over custom Soroban tokens unless you need custom logic.
## When to use this skill
- Issuing a new asset (stablecoin, security token, utility token)
- Setting up trustlines from a client or contract
- Managing issuer flags (auth required, auth revocable, clawback)
- Bridging a classic asset into a Soroban contract via SAC
- Building regulated-asset flows (compliance, KYC, freeze)
## Related skills
- Custom token contracts (when classic isn't enough) → `../soroban/SKILL.md`
- UI flows for trustline creation and asset display → `../dapp/SKILL.md`
- Looking up balances and trustline state → `../data/SKILL.md`
- Token-related SEPs (SEP-41, SEP-7, etc.) → `../standards/SKILL.md`
---
## Overview
Stellar has two token mechanisms:
1. **Stellar Assets (Classic)**: Built-in, highly efficient, full ecosystem support
2. **Soroban Tokens**: Custom contracts with flexible logic
**Recommendation**: Prefer Stellar Assets unless you need custom token logic.
## Stellar Assets (Classic)
### Asset Types
| Type | Description |
|------|-------------|
| Native (XLM) | Stellar's native currency, no trustline needed |
| Credit | Issued by an account, requires trustline |
| Liquidity Pool Shares | Represent LP positions |
### Asset Identifiers
```typescript
import * as StellarSdk from "@stellar/stellar-sdk";
// Native XLM
const xlm = StellarSdk.Asset.native();
// Credit asset (code + issuer)
const usdc = new StellarSdk.Asset(
"USDC",
"GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN"
);
// Asset code rules:
// - 1-4 chars: alphanumeric (credit_alphanum4)
// - 5-12 chars: alphanumeric (credit_alphanum12)
```
## Issuing Assets
### Create Issuing Account
```typescript
import * as StellarSdk from "@stellar/stellar-sdk";
const server = new StellarSdk.Horizon.Server("https://horizon-testnet.stellar.org");
// 1. Create issuing account (should be separate from distribution)
const issuerKeypair = StellarSdk.Keypair.random();
const distributorKeypair = StellarSdk.Keypair.random();
// 2. Fund accounts (testnet)
await fetch(`https://friendbot.stellar.org?addr=${issuerKeypair.publicKey()}`);
await fetch(`https://friendbot.stellar.org?addr=${distributorKeypair.publicKey()}`);
```
### Issue Asset
```typescript
const asset = new StellarSdk.Asset("MYTOKEN", issuerKeypair.publicKey());
// 1. Distributor creates trustline to issuer
const distributorAccount = await server.loadAccount(distributorKeypair.publicKey());
const trustlineTx = new StellarSdk.TransactionBuilder(distributorAccount, {
fee: StellarSdk.BASE_FEE,
networkPassphrase: StellarSdk.Networks.TESTNET,
})
.addOperation(
StellarSdk.Operation.changeTrust({
asset: asset,
limit: "1000000", // Max amount to hold
})
)
.setTimeout(180)
.build();
trustlineTx.sign(distributorKeypair);
await server.submitTransaction(trustlineTx);
// 2. Issuer sends tokens to distributor
const issuerAccount = await server.loadAccount(issuerKeypair.publicKey());
const issueTx = new StellarSdk.TransactionBuilder(issuerAccount, {
fee: StellarSdk.BASE_FEE,
networkPassphrase: StellarSdk.Networks.TESTNET,
})
.addOperation(
StellarSdk.Operation.payment({
destination: distributorKeypair.publicKey(),
asset: asset,
amount: "1000000",
})
)
.setTimeout(180)
.build();
issueTx.sign(issuerKeypair);
await server.submitTransaction(issueTx);
```
### Lock Issuing Account
For fixed-supply tokens, lock the issuer:
```typescript
const lockTx = new StellarSdk.TransactionBuilder(issuerAccount, {
fee: StellarSdk.BASE_FEE,
networkPassphrase: StellarSdk.Networks.TESTNET,
})
.addOperation(
StellarSdk.Operation.setOptions({
masterWeight: 0, // Disable master key
})
)
.setTimeout(180)
.build();
lockTx.sign(issuerKeypair);
await server.submitTransaction(lockTx);
// Issuer can never issue more tokens
```
## Asset Flags
Configure issuer account flags for compliance:
```typescript
const setFlagsTx = new StellarSdk.TransactionBuilder(issuerAccount, {
fee: StellarSdk.BASE_FEE,
networkPassphrase: StellarSdk.Networks.TESTNET,
})
.addOperation(
StellarSdk.Operation.setOptions({
setFlags:
StellarSdk.AuthRequiredFlag | // Trustlines require approval
StellarSdk.AuthRevocableFlag | // Can freeze trustlines
StellarSdk.AuthClawbackEnabledFlag, // Can clawback tokens
})
)
.setTimeout(180)
.build();
```
### Flag Descriptions
| Flag | Effect |
|------|--------|
| `AUTH_REQUIRED` | Users must get approval before receiving tokens |
| `AUTH_REVOCABLE` | Issuer can freeze user balances |
| `AUTH_IMMUTABLE` | Flags cannot be changed (permanent) |
| `AUTH_CLAWBACK_ENABLED` | Issuer can clawback tokens from accounts |
### Authorize Trustline
```typescript
// When AUTH_REQUIRED is set, approve trustlines:
const authorizeTx = new StellarSdk.TransactionBuilder(issuerAccount, {
fee: StellarSdk.BASE_FEE,
networkPassphrase: StellarSdk.Networks.TESTNET,
})
.addOperation(
StellarSdk.Operation.setTrustLineFlags({
trustor: userPublicKey,
asset: asset,
flags: {
authorized: true,
// authorizedToMaintainLiabilities: true, // Partial auth
},
})
)
.setTimeout(180)
.build();
```
### Clawback Tokens
```typescript
// Requires AUTH_CLAWBACK_ENABLED flag
const clawbackTx = new StellarSdk.TransactionBuilder(issuerAccount, {
fee: StellarSdk.BASE_FEE,
networkPassphrase: StellarSdk.Networks.TESTNET,
})
.addOperation(
StellarSdk.Operation.clawback({
asset: asset,
from: targetAccountId,
amount: "100",
})
)
.setTimeout(180)
.build();
```
## Trustlines
### Create Trustline
```typescript
const changeTrustTx = new StellarSdk.TransactionBuilder(userAccount, {
fee: StellarSdk.BASE_FEE,
networkPassphrase: StellarSdk.Networks.TESTNET,
})
.addOperation(
StellarSdk.Operation.changeTrust({
asset: asset,
limit: "10000", // 0 to remove trustline
})
)
.setTimeout(180)
.build();
```
### Check Trustline Status
```typescript
const account = await server.loadAccount(userPublicKey);
const trustline = account.balances.find(
(b) =>
b.asset_type !== "native" &&
b.asset_code === "USDC" &&
b.asset_issuer === usdcIssuer
);
if (trustline) {
console.log("Balance:", trustline.balance);
console.log("Limit:", trustline.limit);
console.log("Authorized:", trustline.is_authorized);
}
```
## Stellar Asset Contract (SAC)
SAC provides Soroban interface for Stellar Assets, enabling smart contract interactions.
### Deploy SAC for Existing Asset
```bash
# Get the SAC address for an asset
stellar contract asset deploy \
--asset USDC:GA5ZSEJYB37JRC5AVCIA5MOP4RHTM335X2KGX3IHOJAPP5RE34K4KZVN \
--source alice \
--network testnet
```
### SAC Address Derivation
```typescript
import * as StellarSdk from "@stellar/stellar-sdk";
const asset = new StellarSdk.Asset("USDC", issuerPublicKey);
const contractId = asset.contractId(StellarSdk.Networks.TESTNET);
// Returns the deterministic SAC contract address
```
### Using SAC in Soroban Contracts
```rust
use soroban_sdk::{token::Client as TokenClient, Address, Env};
pub fn transfer_asset(
env: Env,
from: Address,
to: Address,
asset_contract: Address,
amount: i128,
) {
from.require_auth();
// Use standard token interface
let token = TokenClient::new(&env, &asset_contract);
token.transfer(&from, &to, &amount);
}
```
### SAC vs Custom Token Interface
SAC implements the standard Soroban token interface:
- `balance(id: Address) -> i128`
- `transfer(from: Address, to: Address, amount: i128)`
- `approve(from: Address, spender: Address, amount: i128, expiration_ledger: u32)`
- `allowance(from: Address, spender: Address)Related in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.