This document describes the public interface of the Stellar Forge token-factory Soroban contract deployed on Stellar testnet and mainnet.
The contract binary is built as token_factory.wasm (released alongside the frontend). All function names are lower_snake_case on-chain and translate to camelCase on the frontend wrapper in frontend/src/services/stellar.ts.
| Soroban | TypeScript |
|---|---|
Address |
string (Stellar G... or contract C...) |
u32 |
number |
u64 |
number (lossy above Number.MAX_SAFE_INTEGER) |
i128 |
string (decimal) |
Vec<T> |
T[] |
Option<T> |
T | undefined |
One-time setup. Fails with Error::AlreadyInitialized on retry.
| Param | Type | Description |
|---|---|---|
admin |
Address |
Authority for upgrades, fee updates, pause, and admin transfer. |
treasury |
Address |
Default recipient of factory fees. |
fee_token |
Address |
SEP-41 token used for fee payments. |
token_wasm_hash |
BytesN<32> |
Hash of the token-contract WASM deployed for each new token. |
base_fee |
i128 |
Fee charged for create_token, mint_tokens, create_tokens_batch. |
metadata_fee |
i128 |
Fee charged for set_metadata. |
Stamps FactoryState.schema_version = CURRENT_SCHEMA_VERSION and stores the same value under the legacy sv instance key so migrate works on pre-versioned deployments.
Deploy a new token contract under the factory. Requires fee_payment >= base_fee. Returns the deployed contract address.
Atomically deploy tokens (a Vec<BatchTokenParams>). Requires fee_payment >= base_fee * tokens.len(). Partial-batch failure rolls state back to pre-call values.
Mint amount of token_address to to. Rejects when a max_supply cap would be exceeded (Error::MaxSupplyExceeded).
Burn amount of token_address from from's balance. Honors burn_enabled; rejects when disabled.
Set an IPFS / HTTPS metadata URI for an existing token. One-shot — re-setting returns Error::MetadataAlreadySet.
Toggle the burn flag for a token.
Inspect factory configuration and aggregate counts.
Current base fee.
Current set-metadata fee.
Look up a single token by 1-based index. Returns Error::TokenNotFound for unknown indices.
Return a paginated slice of token indices owned by creator. This replaces an earlier non-paginated version that returned the full Vec<u32> (which could exceed Stellar ledger entry size limits on creators with hundreds of registered tokens).
| Param | Type | Description |
|---|---|---|
creator |
Address |
Creator whose tokens to list. |
offset |
u32 |
0-based index of the first element to return. |
limit |
u32 |
Maximum number of elements to return. Capped server-side at MAX_TOKENS_BY_CREATOR_PAGE (currently 50) so callers cannot request pathologically large pages. |
Returns: Vec<u32> of token indices, len ≤ min(limit, MAX_TOKENS_BY_CREATOR_PAGE). Use the indices with get_token_info to materialize each token's TokenInfo.
Behavior:
| Input | Output |
|---|---|
limit == 0 |
empty Vec (defensive — read-only path, no error) |
limit > MAX_TOKENS_BY_CREATOR_PAGE |
clamped down to the cap |
offset >= total_tokens_for_creator |
empty Vec (past-the-end) |
| Unknown creator | empty Vec |
| Otherwise | slice [offset, offset + min(limit, cap, remaining)) |
To iterate the full list:
- Call with
offset = 0, limit = 50. - If response.length < 50 → you're done.
- Otherwise advance
offset += response.lengthand repeat.
The frontend helper fetchAllTokensByCreator in frontend/src/hooks/useTokens.ts does this loop automatically.
Adjust either fee. None leaves the corresponding fee unchanged.
Toggle factory-wide pause. create_token, create_tokens_batch, mint_tokens, and set_metadata honor the pause; burn does not (users can always burn their own balance).
Set a fee split where splits is a Map<Address, u32> of basis-point recipients summing to 10_000. Empty map clears the split (full fee goes back to treasury).
Read the current split (empty map means no split).
Hand the admin privilege to new_admin. Both events emit the same effect; update_admin additionally emits an adm_upd event for off-chain tracking.
Replace the factory code in place while preserving state.
Incrementally upgrades state between schema versions. Idempotent.
| Code | Symbol | When |
|---|---|---|
| 1 | InsufficientFee |
fee_payment < required_fee |
| 2 | Unauthorized |
caller is not allowed for this operation |
| 3 | InvalidParameters |
argument out of range or malformed |
| 4 | TokenNotFound |
unknown token index or address |
| 5 | MetadataAlreadySet |
set_metadata called twice |
| 6 | AlreadyInitialized |
double-initialize attempt |
| 7 | BurnAmountExceedsBalance |
burn > balance |
| 8 | BurnNotEnabled |
burning on a token that has been disabled |
| 9 | InvalidBurnAmount |
zero or negative burn |
| 10 | ContractPaused |
operation blocked because factory is paused |
| 11 | Reentrancy |
concurrent reentrant call detected |
| 12 | ArithmeticOverflow |
checked-op failed |
| 13 | StateNotFound |
factory not yet initialized |
| 14 | InvalidTokenParams |
name/symbol validation failed during token creation |
| 15 | InvalidDecimals |
decimals outside [0, 18] |
| 16 | MaxSupplyExceeded |
mint would exceed cap |
| 17 | InvalidFeeSplit |
set_fee_split map bps do not sum to 10_000 |
The contract emits Soroban events on a (factory, action) topic. The frontend parses them via frontend/src/services/stellar-impl.ts. Events:
| Action | Payload | Trigger |
|---|---|---|
init |
(admin) |
initialize |
created |
(token_address, creator, name, symbol) |
create_token / create_tokens_batch |
meta |
(token_address, metadata_uri) |
set_metadata |
mint |
(token_address, to, amount) |
mint_tokens |
burn |
(token_address, from, amount) |
burn |
fees |
(base_fee, metadata_fee) |
update_fees |
pause |
(admin) |
pause |
unpause |
(admin) |
unpause |
adm_upd |
(current_admin, new_admin) |
update_admin |