> ## 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.

# Getting Started with LayerZero V2 on Starknet

> Learn how to build crosschain applications on Starknet with LayerZero V2. Covers Cairo fundamentals, account abstraction, and development setup.

Any data, whether it's a fungible token transfer, an NFT, or some other smart contract input can be encoded on-chain as bytes and delivered to a destination chain to trigger some action using LayerZero.

Because of this, any blockchain that broadly supports state propagation and events can be connected to LayerZero, including **Starknet**.

<Tip>
  If you're new to LayerZero, we recommend reviewing [**"What is LayerZero?"**](/v2/concepts/getting-started/what-is-layerzero) before continuing.
</Tip>

<br />

LayerZero provides **Starknet Cairo Contracts** that can communicate with the equivalent [Solidity Contract Libraries](/v2/developers/evm/overview) and [Solana Programs](/v2/developers/solana/overview) deployed on other chains.

These contracts, like their Solidity and Rust counterparts, simplify calling the [LayerZero Endpoint](/v2/concepts/protocol/layerzero-endpoint), provide message handling, interfaces for protocol configurations, and other utilities for interoperability:

* **Omnichain Fungible Token (OFT)**: extends OApp with functionality for handling omnichain token transfers using Starknet's ERC20 standard.

* **Omnichain Application (OApp)**: the base contract utilities for omnichain messaging and configuration.

Each of these contract standards implements common functions for **sending** and **receiving** omnichain messages.

## Differences from the Ethereum Virtual Machine

The full differences between Solidity/EVM and Cairo/Starknet are significant. For comprehensive guides, see:

* [Starknet Documentation](https://docs.starknet.io/)
* [The Cairo Book](https://book.cairo-lang.org/)
* [Cairo by Example](https://cairo-by-example.com/)

<Info>
  Skip this section if you already feel comfortable working with Starknet and its account abstraction model.
</Info>

### Comparison Table

| Aspect             | EVM                | Starknet                                                                                                                 |
| ------------------ | ------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| **State Model**    | Storage slots      | Felt-based contract storage                                                                                              |
| **Language**       | Solidity           | Cairo                                                                                                                    |
| **Authorization**  | `msg.sender`       | `get_caller_address()`                                                                                                   |
| **Cross-Contract** | External calls     | [Dispatcher pattern](https://book.cairo-lang.org/ch102-02-interacting-with-another-contract.html#the-dispatcher-pattern) |
| **OApp Identity**  | Contract address   | Contract address                                                                                                         |
| **Balance Type**   | `uint256`          | `u256` (struct: two `u128`)                                                                                              |
| **Fee Model**      | Gas (ETH)          | Resource bounds (STRK/ETH)                                                                                               |
| **Account Model**  | EOA + Contracts    | Account Abstraction (all accounts are contracts)                                                                         |
| **Deployment**     | Single transaction | Declare + Deploy (two steps)                                                                                             |

### Account Abstraction (No EOAs)

The most fundamental difference is Starknet's **native account abstraction**:

**EVM**:

```solidity wrap theme={null}
// EOA (Externally Owned Account) signs and sends transactions directly
// msg.sender is the account that signed the transaction
function transfer() external {
    require(msg.sender == owner, "not owner");
}
```

**Starknet**:

```rust wrap theme={null}
// All accounts are smart contracts
// Signatures are produced off-chain and validated by the account contract
// get_caller_address() returns the account contract address
fn transfer(ref self: ContractState) {
    let caller = get_caller_address();
    assert(caller == self.owner.read(), 'not owner');
}
```

**Key Implications**:

* **Before deploying any contract**, you must have a deployed and funded account contract (wallet)
* Signatures are produced off-chain by the account owner and validated by the account contract
* Account contracts handle fee payment and transaction execution for that account
* Common account implementations include Ready Wallet (formerly Argent), Braavos, and OpenZeppelin Account

### Declare Then Deploy Lifecycle

Unlike EVM where you deploy bytecode in a single transaction, Starknet separates code publication from instantiation:

```mermaid theme={null}
flowchart LR
    A[Build Cairo] --> B[Declare Class]
    B --> C[Get class_hash]
    C --> D[Deploy Instance]
    D --> E[Contract Address]
```

**Step 1: Declare** - Publish your contract code to the network:

```bash theme={null}
sncast declare --contract-name MyOFT
# Returns: class_hash = 0x123abc...
```

**Step 2: Deploy** - Create an instance of the declared class:

```bash theme={null}
sncast deploy --class-hash 0x123abc... --network sepolia --arguments '<args>'
# Returns: contract_address = 0x456def...
```

**Key Concepts**:

* **class\_hash**: Unique identifier for your contract's code (like a "template")
* **contract\_address**: Specific instance of that code with its own state
* **Multiple contracts** can share the same class\_hash (reusable code)

### Dispatcher Pattern vs Inheritance

Starknet uses the [dispatcher pattern](https://book.cairo-lang.org/ch102-02-interacting-with-another-contract.html#the-dispatcher-pattern) instead of Solidity's inheritance model.

**EVM uses inheritance** for contract composition:

```solidity wrap theme={null}
// Solidity: Inherit and override
contract MyOFT is OFT {
    constructor() OFT("Token", "TKN", endpoint, owner) {}
}
```

**Starknet uses components and dispatchers**:

```rust wrap theme={null}
// Cairo: Compose with components
#[starknet::contract]
mod MyOFT {
    // Import components
    use layerzero::oapps::oapp::oapp_core::OAppCoreComponent;
    use openzeppelin::token::erc20::ERC20Component;

    // Declare components
    component!(path: OAppCoreComponent, storage: oapp_core, event: OAppCoreEvent);
    component!(path: ERC20Component, storage: erc20, event: ERC20Event);

    // Embed implementations
    #[abi(embed_v0)]
    impl OAppCoreImpl = OAppCoreComponent::OAppCoreImpl<ContractState>;
}
```

**Cross-contract calls use dispatchers**:

```rust wrap theme={null}
// Cairo: Typed dispatcher for cross-contract calls
use layerzero::endpoint::interfaces::endpoint_v2::{IEndpointV2Dispatcher, IEndpointV2DispatcherTrait};

fn call_endpoint(endpoint_address: ContractAddress) {
    let endpoint = IEndpointV2Dispatcher { contract_address: endpoint_address };
    let fee = endpoint.quote(params, sender);  // Type-safe call
}
```

### Constructor Caller Footgun

<Warning>
  When deploying via the Universal Deployer Contract (UDC), `get_caller_address()` in the constructor returns the **UDC address**, not your account address!
</Warning>

**Problem**:

```rust wrap theme={null}
#[constructor]
fn constructor(ref self: ContractState, endpoint: ContractAddress) {
    // BUG: If deployed via UDC, this sets UDC as owner!
    let caller = get_caller_address();
    self.ownable.initializer(caller);
}
```

**Solution** - Always pass the owner explicitly:

```rust wrap theme={null}
#[constructor]
fn constructor(
    ref self: ContractState,
    endpoint: ContractAddress,
    owner: ContractAddress,  // Explicitly pass the intended owner
) {
    self.ownable.initializer(owner);
}
```

### Cairo Integer Types

Cairo 1.0 provides native unsigned integer types. For **token amounts** (ERC20 balances, transfers, allowances), always use `u256`—matching Solidity's `uint256` for crosschain compatibility.

| Type   | Size    | Use Case                                      |
| ------ | ------- | --------------------------------------------- |
| `u64`  | 64-bit  | Timestamps, small counters                    |
| `u128` | 128-bit | Medium-sized values                           |
| `u256` | 256-bit | **Token amounts** (ERC20 balances, transfers) |

OpenZeppelin's Cairo ERC20 interface uses `u256` for `balance_of`, `total_supply`, `allowance`, and all transfer/approve amounts.

```rust wrap theme={null}
// u256 for token amounts (matches Solidity uint256)
let amount: u256 = 1000000000000000000_u256;  // 1 token (18 decimals)

fn balance_of(self: @ContractState, account: ContractAddress) -> u256 {
    self.erc20.balance_of(account)
}
```

<Note>
  You'll also encounter `felt252` in Cairo—it's Starknet's base field element type used internally (e.g., `ContractAddress` wraps a `felt252`). However, don't use it for token amounts; its modular arithmetic can cause unexpected behavior.
</Note>

**Crosschain encoding**: LayerZero messages encode addresses as `Bytes32` for compatibility across chains with different address sizes.

### Resource Bounds (Gas Model)

Starknet uses **resource bounds** instead of simple gas limits:

```rust wrap theme={null}
// INVOKE v3 transactions include resource bounds:
// - l1_gas: Max L1 gas willing to pay
// - l2_gas: Max L2 gas (compute) willing to pay
// - l1_data_gas: Max L1 data availability gas
```

**Common error**: "Insufficient max fee" - increase your resource bounds (or fee cap in tooling):

```bash theme={null}
sncast deploy --class-hash 0x...
```

## Prerequisites

Before you start building, you'll need to set up your development environment.

### 1. Deploy and Fund an Account Contract

Unlike EVM, you need an account contract before you can deploy other contracts:

##### Create a new account (generates keys and computes address)

```bash theme={null}
sncast account create \
  --name my_account \
  --type oz \
  --url <YOUR_SEPOLIA_RPC_URL>
```

##### Fund the computed address with STRK/ETH before deploying.

The `account create` command outputs the computed address. Fund this address using a [faucet](https://starknet-faucet.vercel.app/) before running `account deploy`.

##### Deploy the account contract

```bash theme={null}
sncast account deploy \
  --name my_account \
  --url <YOUR_SEPOLIA_RPC_URL>
```

### 2. Account File Location

Accounts are stored in `~/.starknet_accounts/starknet_open_zeppelin_accounts.json`:

```json theme={null}
{
  "alpha-sepolia": {
    "my_account": {
      "address": "0x...",
      "deployed": true,
      "legacy": false,
      "private_key": "0x...",
      "public_key": "0x...",
      "salt": "0x..."
    }
  }
}
```

### 3. Install Scarb (Cairo Build Tool)

[Scarb](https://docs.swmansion.com/scarb/) is the official Cairo package manager and build tool:

```bash theme={null}
# Install via asdf
asdf plugin add scarb
asdf install scarb 2.14.0
asdf set scarb 2.14.0
```

Verify installation:

```bash theme={null}
scarb --version
# scarb 2.14.0 or later
```

### 4. Install Starknet Foundry (sncast + snforge)

[Starknet Foundry](https://foundry-rs.github.io/starknet-foundry/) provides `sncast` (deployment) and `snforge` (testing):

```bash theme={null}
# Install via asdf
asdf plugin add starknet-foundry
asdf install starknet-foundry 0.53.0
asdf set starknet-foundry 0.53.0
```

Verify installation:

```bash theme={null}
sncast --version
snforge --version
```

<Warning>
  **RPC Version Compatibility**

  sncast requires a compatible RPC version:

  * **Starknet Foundry 0.53.0+** expects RPC v0.9.0 or v0.10.0
  * **Starknet Foundry 0.49.0** expects RPC v0.9.0

  If you see `RPC node uses incompatible version` warnings, update your RPC URL to use a compatible version:

  ```
  # For v0.9.0 (Alchemy)
  https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_9/<key>

  # For v0.10.0 (Alchemy)
  https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_10/<key>
  ```
</Warning>

### 5. Configure snfoundry.toml

Create a `snfoundry.toml` in your project root to configure `sncast` defaults:

```toml wrap theme={null}
[sncast.default]
account = "my_account"
url = "https://starknet-sepolia.g.alchemy.com/starknet/version/rpc/v0_9/<YOUR_API_KEY>"
wait-params = { timeout = 300, retry-interval = 10 }
block-explorer = "StarkScan"
show-explorer-links = true
```

| Field                 | Description                                                           |
| --------------------- | --------------------------------------------------------------------- |
| `account`             | Account name from your accounts file                                  |
| `url`                 | RPC endpoint URL (must match sncast version; see RPC note above)      |
| `wait-params`         | Transaction wait timeout and retry settings                           |
| `block-explorer`      | Explorer for transaction links (`StarkScan`, `Blockchain`, `Voyager`) |
| `show-explorer-links` | Show explorer links after transactions                                |

Use `sncast account list` to see available account names.

### 6. Install Node.js

For any TypeScript tooling or SDK usage:

```bash theme={null}
# Using nvm (recommended)
nvm install 20
nvm use 20

# Verify
node --version
# v20.x.x
```

### 7. Get Testnet STRK/ETH

For testing on Starknet Sepolia testnet:

* [Starknet Faucet](https://starknet-faucet.vercel.app/) - Get testnet STRK
* [Starkgate Bridge](https://sepolia.starkgate.starknet.io/) - Bridge ETH from Ethereum Sepolia

## Project Structure

A typical LayerZero Starknet project structure:

```
my-oft-project/
├── Scarb.toml              # Package manifest (dependencies)
├── snfoundry.toml          # Starknet Foundry config
├── src/
│   ├── lib.cairo           # Module declarations
│   └── my_oft.cairo        # Your OFT contract
└── tests/
    └── test_my_oft.cairo   # Contract tests
```

**Example `Scarb.toml`**:

```toml wrap theme={null}
[package]
name = "my_oft"
version = "0.1.0"
edition = "2024_07"

[dependencies]
starknet = "2.14.0"
openzeppelin = "2.0.0"
lz_utils = { path = "./node_modules/@layerzerolabs/protocol-starknet-v2/libs/lz_utils" }
layerzero = { path = "./node_modules/@layerzerolabs/protocol-starknet-v2/layerzero" }

[dev-dependencies]
snforge_std = "0.53.0"

[[target.starknet-contract]]
sierra = true
casm = true
```

<Info>
  **Installing LayerZero Packages**

  Before building, install the LayerZero Cairo contracts:

  ```bash theme={null}
  npm init -y
  npm install @layerzerolabs/protocol-starknet-v2
  ```
</Info>

## Network Configuration

| Network          | Endpoint ID | Chain ID     |
| ---------------- | ----------- | ------------ |
| Starknet Mainnet | `30500`     | `SN_MAIN`    |
| Starknet Sepolia | `40500`     | `SN_SEPOLIA` |

> `SN_MAIN` and `SN_SEPOLIA` are [Starknet's native chain-id identifiers](https://docs.starknet.io/chain-info/), defined by the Starknet protocol to identify the target network for transactions.

**RPC Endpoints**:

* Mainnet: `<YOUR_MAINNET_RPC_URL>`
* Sepolia: `<YOUR_SEPOLIA_RPC_URL>`

<Note>
  **RPC providers**

  Blast public endpoints are deprecated; use Alchemy, Infura, or another provider that supports Starknet JSON-RPC v0.9+.
</Note>

## Next Steps

Choose your path:

### Build an OApp

For custom crosschain logic:

* [OApp Overview](/v2/developers/starknet/oapp/overview) - Architecture and patterns
* [Protocol Overview](/v2/developers/starknet/protocol-overview) - Deep technical dive
* [Technical Overview](/v2/developers/starknet/technical-overview) - Starknet fundamentals

### Build an OFT

For crosschain tokens:

* [OFT Overview](/v2/developers/starknet/oft/overview) - Token architecture
* [Configuration Guide](/v2/developers/starknet/configuration/dvn-executor-config) - Security and DVN setup

### Understand the Protocol

For protocol-level understanding:

* [Technical Overview](/v2/developers/starknet/technical-overview) - Cairo architecture and patterns
* [Protocol Overview](/v2/developers/starknet/protocol-overview) - Complete message workflows

### Get Help

* [Troubleshooting](/v2/developers/starknet/troubleshooting/common-errors) - Common issues
* [FAQ](/v2/developers/starknet/troubleshooting/faq) - Frequently asked questions
* [Discord](https://discord.com/invite/ktbvm8Nkcr) - Community support
