> ## Documentation Index
> Fetch the complete documentation index at: https://docs.layerzero.network/llms.txt
> Use this file to discover all available pages before exploring further.

# Stellar FAQ

> Frequently asked questions about building LayerZero applications on Stellar Soroban.

<AccordionGroup>
  ## General

  <Accordion title="What smart contract language does Stellar use?">
    Stellar uses [Soroban](https://soroban.stellar.org/), a smart contract platform where contracts are written in **Rust** and compiled to **WebAssembly (WASM)**. The primary SDK is `soroban-sdk` (v25.1.1 for LayerZero contracts).
  </Accordion>

  <Accordion title="How is LayerZero's Stellar integration different from EVM?">
    Key differences include:

    * **Authorization**: Uses `require_auth()` instead of `msg.sender`
    * **Token standard**: SEP-41 instead of ERC-20
    * **Contract composition**: Trait composition with proc macros instead of inheritance
    * **Storage**: Three-tiered storage (instance, persistent, temporary) with TTL management
    * **Fee payment**: Explicit SEP-41 token transfer instead of `msg.value`
    * **Address format**: 32 bytes (contract or account) instead of 20 bytes

    See the [Technical Overview](/v2/developers/stellar/technical-overview) for a detailed comparison.
  </Accordion>

  <Accordion title="Do I need to deploy my own Endpoint?">
    No. LayerZero deploys and maintains the Endpoint V2 contract on Stellar. You only need to:

    1. Deploy your OApp or OFT contract, passing the Endpoint address in the constructor
    2. Set peers for each remote chain
    3. Configure enforced options and security stack (DVNs)

    See [OApp Overview](/v2/developers/stellar/oapp/overview) for the deployment flow.
  </Accordion>

  ## Development

  <Accordion title="What Rust version should I use?">
    Use Rust 1.90.0 or later with the `wasm32v1-none` target. Pin your version with a `rust-toolchain.toml` file:

    ```toml wrap theme={null}
    [toolchain]
    channel = "1.90.0"
    targets = ["wasm32v1-none"]
    ```
  </Accordion>

  <Accordion title="How do I use the #[oapp] macro?">
    The `#[oapp]` macro generates implementations for `OAppCore`, `OAppSenderInternal`, `OAppReceiver`, and `OAppOptionsType3`. Apply it to your contract struct together with `#[lz_contract]`:

    ```rust wrap theme={null}
    #[lz_contract]
    #[oapp]
    pub struct MyOApp;
    ```

    You must always implement `LzReceiveInternal` for your receive logic. To customize specific traits, use `#[oapp(custom = [receiver])]`.
  </Accordion>

  <Accordion title="What is the difference between LockUnlock and MintBurn OFT modes?">
    * **LockUnlock**: Tokens are locked in the OFT contract on send and unlocked on receive. Use this when you don't control the token's minting capability.
    * **MintBurn**: Tokens are burned on send and minted on receive via an external `Mintable` contract. Use this when you control the token supply.

    Both modes are configured at deployment via the `OftType` enum in the constructor.
  </Accordion>

  <Accordion title="How do I handle the two address types (C-address vs G-address)?">
    Stellar has contract addresses (C-addresses) and account addresses (G-addresses), both 32 bytes. LayerZero's `resolve_address` utility handles disambiguation automatically by checking if a contract exists at the address. You typically don't need to handle this yourself -- the OFT contract resolves addresses when crediting tokens to recipients.
  </Accordion>

  <Accordion title="How do I handle decimal precision for OFTs?">
    OFTs use **shared decimals** for crosschain consistency:

    * **Local decimals**: Token's native decimals on the chain (e.g., 7 for Stellar)
    * **Shared decimals**: Crosschain precision (typically 6)
    * **Conversion rate**: `10^(local - shared)`

    When sending, amounts are divided by the conversion rate, removing dust. The truncated amount is sent crosschain, and the destination multiplies by its own conversion rate.

    For example, with local decimals = 7 and shared decimals = 6, the conversion rate is 10. An amount of `1,000,015` becomes `1,000,010` (the trailing 5 is dust).

    `shared_decimals` is set at deployment and **cannot be changed**. Use 6 for compatibility with most chains.

    See [OFT Overview - Decimal Precision](/v2/developers/stellar/oft/overview#decimal-precision) for details.
  </Accordion>

  ## Gas and Fees

  <Accordion title="How are LayerZero fees paid on Stellar?">
    Unlike EVM where fees are paid via `msg.value`, Stellar requires explicit SEP-41 token transfers. The OApp base contract handles this internally -- it transfers XLM (native token) to the Endpoint before calling `send`. As a developer, you just pass the fee from the quote function (`__quote` for OApp, `quote_send` for OFT) to the send function.
  </Accordion>

  <Accordion title="How does Soroban's fee model work?">
    Soroban uses resource-based fees rather than gas. You're charged for:

    * **CPU instructions**: Computation cost
    * **Memory**: Runtime memory allocation
    * **Storage I/O**: Read/write bytes and entries
    * **Transaction size**: Byte size of the transaction

    Transactions declare resource limits upfront. The Stellar CLI estimates these automatically during simulation.
  </Accordion>

  <Accordion title="Why are storage operations expensive?">
    Soroban storage operations are priced to reflect the real cost of maintaining ledger state. Each storage entry requires rent to maintain its TTL. Writing to persistent storage is more expensive than temporary storage. To minimize costs, keep your storage footprint small and use temporary storage where possible.
  </Accordion>

  ## Configuration

  <Accordion title="How do I configure DVNs on Stellar?">
    DVN configuration is done through the ULN-302 message library via the Endpoint's `set_config` function. You provide an XDR-encoded `OAppUlnConfig` with config type `2` (send) or `3` (receive). See [DVN & Executor Config](/v2/developers/stellar/configuration/dvn-executor-config) for detailed instructions.
  </Accordion>

  <Accordion title="What are enforced options and why should I set them?">
    Enforced options define the **minimum execution parameters** (gas limit, native value) for messages sent to each destination. Without them, messages may fail on the destination chain due to insufficient gas. Always set enforced options for each destination and message type.

    ```bash wrap theme={null}
    stellar contract invoke \
      --id <YOUR_OAPP_ADDRESS> \
      --network testnet \
      --source my-account \
      -- \
      set_enforced_options \
      --options '[{"eid": <DST_EID>, "msg_type": 1, "options": "<OPTIONS_HEX>"}]' \
      --operator <OWNER_ADDRESS>
    ```
  </Accordion>

  <Accordion title="Why does XDR encoding matter for configuration?">
    Where EVM uses ABI encoding, Soroban uses XDR (External Data Representation) for config encoding. This means ULN configs, executor configs, and other message library settings are XDR-encoded. The TypeScript SDK handles this automatically, but if you're using CLI directly, you'll need to provide XDR-encoded config values.
  </Accordion>

  <Accordion title="Can I change configuration after deployment?">
    Yes. The contract **owner** can modify:

    * **Peers**: `set_peer` to add or update remote chain connections
    * **Enforced options**: `set_enforced_options` to adjust gas limits per destination
    * **Delegate**: `set_delegate` to assign or change the operational delegate

    The **delegate** can configure:

    * **Message libraries**: Send and receive library selection
    * **DVN and Executor settings**: Via the Endpoint's `set_config` function

    See [DVN & Executor Config](/v2/developers/stellar/configuration/dvn-executor-config) for configuration details.
  </Accordion>

  ## Troubleshooting

  <Accordion title="My message was sent but not received. What should I check?">
    1. **Check LayerZero Scan**: Look up the message GUID on [LayerZero Scan](https://layerzeroscan.com/) to see its status.
    2. **Verify peers**: Ensure peers are set on both the source and destination chains.
    3. **Check DVN status**: The message may be waiting for DVN verification. Use the receive library's `verifiable` (e.g. on ULN-302) to check whether DVNs have reached quorum.
    4. **Check executor**: The executor may not have delivered yet. Check `endpoint.inbound_payload_hash(receiver, src_eid, sender, nonce)` to see if it's been verified but not delivered.
    5. **Check enforced options**: Insufficient gas on the destination can cause delivery to fail silently.
  </Accordion>

  <Accordion title="How do I recover a stuck message?">
    If a message is verified but delivery fails, you have several recovery options:

    * **Retry delivery**: The executor will typically retry automatically.
    * **Skip**: Skip the nonce if using ordered delivery: `endpoint.skip()`
    * **Nilify**: Void the message (can be re-verified later): `endpoint.nilify()`
    * **Burn**: Permanently destroy a nonce (irreversible): `endpoint.burn()`
    * **Clear**: Remove the payload: `endpoint.clear()`

    See [Technical Overview - Recovery Operations](/v2/developers/stellar/technical-overview#recovery-operations) for details.
  </Accordion>

  <Accordion title="I'm getting 'ArchivedEntry' errors. What happened?">
    Soroban persistent storage entries have a TTL. If the TTL expires, the entry is archived (not deleted, but inaccessible until restored). This can happen to peer mappings, rate limit state, or other persistent data if the contract hasn't been called for an extended period.

    **Solution:** Restore the entry with `stellar contract restore` or call any function that accesses the entry (TTL is automatically extended on access).
  </Accordion>

  ## Security

  <Accordion title="How does the 2-step ownership transfer work?">
    To prevent accidental ownership loss, use the 2-step flow:

    1. Current owner calls `begin_ownership_transfer(new_owner, ttl)` -- proposes transfer with a TTL window
    2. New owner calls `accept_ownership()` -- confirms within the TTL
    3. If not accepted in time, the proposal expires and the original owner retains ownership

    A single-step `transfer_ownership` is also available but is immediate and irreversible.

    This ensures the new owner can actually receive and operate the contract.
  </Accordion>

  <Accordion title="How are DVNs authenticated on Stellar?">
    DVNs on Stellar are implemented as Soroban custom account contracts with multisig verification. They use secp256k1 signatures (compatible with EVM signers) for the multisig quorum, plus an optional Ed25519 admin key. Transaction data is hashed with keccak256, enabling crosschain signer reuse.
  </Accordion>
</AccordionGroup>

## Next Steps

* **[Common Errors](/v2/developers/stellar/troubleshooting/common-errors)**: Detailed error codes and solutions.
* **[Getting Started](/v2/developers/stellar/getting-started)**: Key differences between EVM and Stellar development.
* **[Technical Overview](/v2/developers/stellar/technical-overview)**: Deep dive into Soroban architecture.
