Skip to main content

Smart Contracts

Stellar smart contracts related data are stored in various ledger entries. In summary:

  • Contract Code (Wasm bytecode): Stored as a CONTRACT_DATA ledger entry, identified by its Wasm hash.

  • Contract Instance: Contract instances are stored in separate ledger entries. Contract instance references Wasm bytecode, but has its own data, state, and configuration.

  • Data Storage: Data tied to contract instances. Comes in three types—Temporary, Persistent, and Instance—each with its own cost, TTL (time-to-live), and restoration rules.

WebAssembly (Wasm)

Once a smart contract has been written by a developer and compiled into a Wasm executable file, it can then be uploaded onto the Stellar network. A CONTRACT_DATA ledger entry is created to store this binary data and its unique identifier is the hash of the executable file. This binary executable is stored independently from its deployed contract(s). When a Stellar transaction attempts to invoke a contract function, the Wasm bytecode is first retrieved from the ledger and a secure, isolated runtime virtual machine ("VM") is instantiated so it can run the bytecode for the contract and then exit.

Wasm Compilation and Upload

Once a developer writes a smart contract in a supported language, such as Rust, the contract is compiled into a Wasm executable file. This file contains low-level bytecode that can be efficiently executed within a sandboxed environment. After compilation, the Wasm executable is uploaded on the Stellar network, where it is stored as a CONTRACT_DATA ledger entry . The unique identifier for this entry is derived from the hash of the compiled binary and is called Wasm hash.

To retrieve Wasm executable file from the Stellar network to upload in your local network, it is possible to do so using the RPC's getLedgerEntries or use Stellar Lab's Contract Explorer.

Wasm and Host Functions

Stellar’s Wasm-based smart contracts interact with the protocol through host functions—predefined operations that allow contracts to read from and write to the ledger. These host functions abstract away low-level blockchain interactions, providing developers with a simplified yet powerful interface for building decentralized applications. To learn more about host functions and environments, read Environment Concepts.

Contract instances

info

Importantly, the Wasm bytecode itself is stored separately from the deployed contract instances. This separation allows multiple contract instances to reference the same Wasm executable while maintaining their own state and configurations.

After the executable bytecode is uploaded on-chain, contract instances can be deployed that reference the aformentioned bytecode. A smart contract executable can have a one-to-many relationship with "contract instances" which function independently. This means the same executable code can be used by multiple contract instances that all behave identically (because of the shared executable code), while maintaining separate and distinct state data (because the data is tied to the contract instance). A contract instance is stored as its own ledger entry, and any of the contract's instance storage is stored in that same ledger entry alongside the contract instance.

Contract storage

In addition to the ledger entries that are created during the contract upload/deploy process, each contract can create and access its own set of ledger entries. These ledger entries (as well as the contract code and the contract instance ledger entries) are subject to state archival lifetimes (a ledger entry's "TTL ledger"). While they all function similarly, each type has its own fee and TTL behavior.

Temporary storage

  • Cheapest fees.
  • Permanently deleted when its TTL ledger is reached, cannot be restored.
  • Suitable for time-bounded data (i.e. price oracles, signatures, etc.) and easily recreateable data.
  • Unlimited amount of storage.

Persistent storage

  • Most expensive fees (same price as Instance storage).
  • Recoverable after archival, can be restored using the RestoreFootprintOp operation.
  • Does not share the same lifetime as the contract instance. If the contract instance has not reached its TTL ledger, Persistent data may still be archived and need to be restored before invoking the contract.
  • Unlimited amount of storage.
  • Suitable for user data that cannot be Temporary (i.e. balances).

Instance storage

info

While we are making a distinction here between "persistent" and "instance" storage, instance storage is really just a convenient, abstracted type of persistent storage. Under the hood, the instance storage works the same as persistent storage, except its own TTL is tied to that of the contract instance.

  • Most expensive fees (same price as Persistent storage).
  • Recoverable after archival, can be restored using the extendFootprintTTLOp operation.
  • Shares the same lifetime as the contract instance. If the contract instance has not reached its TTL ledger, instance data is guaranteed to be accessible.
  • Limited amount of storage available.
  • Suitable for "shared" contract state that cannot be Temporary (i.e. admin accounts, contract metadata, etc.).
note

Learn to write a smart contract on Stellar by following this Getting Started guide.