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

# Starknet Development Guidance

> Testing, networking, authority management, constraints, and upgradeability for LayerZero contracts on Starknet.

This guide covers testing, networking, authority management, constraints, and upgradeability for LayerZero contracts on Starknet. For toolchain installation and account setup, see [Getting Started](/v2/developers/starknet/getting-started). For project scaffolding and deployment steps, see the OApp and OFT overviews.

## Project Scaffolding, Build, and Deploy

For project layout, `Scarb.toml`, build, declare/deploy, and verification steps, see:

* [OApp Overview](/v2/developers/starknet/oapp/overview)
* [OFT Overview](/v2/developers/starknet/oft/overview)

***

## Testing

### Running Tests

```bash theme={null}
# Run all tests
snforge test

# Run specific test
snforge test test_send_tokens

# Run tests with detailed traces
snforge test --trace-verbosity detailed

# Run tests matching pattern
snforge test test_oft
```

### Test Structure

```rust wrap theme={null}
use snforge_std::{
    declare, ContractClassTrait, DeclareResultTrait,
    start_cheat_caller_address, stop_cheat_caller_address,
};

#[test]
fn test_oft_send() {
    // Deploy contract
    let contract = declare("MyOFT").unwrap().contract_class();
    let constructor_calldata = array![
        endpoint.into(),
        owner.into(),
        native_token.into(),
    ];
    let (contract_address, _) = contract.deploy(@constructor_calldata).unwrap();

    // Create dispatcher
    let oft = IOFTDispatcher { contract_address };

    // Cheat caller for owner operations
    start_cheat_caller_address(contract_address, owner);

    // Set peer
    oft.set_peer(30101, peer_address);

    // Verify
    let stored_peer = oft.get_peer(30101);
    assert(stored_peer == peer_address, 'peer mismatch');

    stop_cheat_caller_address(contract_address);
}
```

### Test Utilities

```rust wrap theme={null}
use snforge_std::{
    start_cheat_caller_address,  // Mock caller
    stop_cheat_caller_address,
    start_cheat_block_timestamp, // Mock block time
    stop_cheat_block_timestamp,
    spy_events,                  // Capture events
    EventSpyAssertionsTrait,
};
```

***

## Network Configuration

<Tip>
  **Endpoint IDs and addresses**

  For up-to-date Starknet endpoint IDs and LayerZero contract addresses, use [V2 Protocol Contracts](/v2/deployments/deployed-contracts) or query the [Endpoint Metadata API](https://metadata.layerzero-api.com/v1/metadata).
</Tip>

### RPC Endpoints

| Network | URL                                               |
| ------- | ------------------------------------------------- |
| Mainnet | `<YOUR_MAINNET_RPC_URL>`                          |
| Sepolia | `<YOUR_SEPOLIA_RPC_URL>`                          |
| Alchemy | `https://starknet-mainnet.g.alchemy.com/v2/<key>` |
| Infura  | `https://starknet-mainnet.infura.io/v3/<key>`     |

### LayerZero Contract Addresses

Check the [LayerZero Deployments](/v2/deployments/deployed-contracts) page for current addresses:

| Contract      | Address              |
| ------------- | -------------------- |
| EndpointV2    | See deployments page |
| ULN302        | See deployments page |
| LayerZero DVN | See deployments page |
| Executor      | See deployments page |

***

## Public Key vs Address

Starknet accounts are smart contracts (native account abstraction), so an account address is a contract address, not a public-key-derived identifier. There is no default deterministic link between the key(s) controlling an account and its address, and keys can be rotated by the account logic. See [Accounts](https://docs.starknet.io/learn/protocol/accounts) and [Account keys and addresses derivation standard](https://community.starknet.io/t/account-keys-and-addresses-derivation-standard/1230).

Practical takeaways:

* Use the account address anywhere an API expects a `ContractAddress`.
* Treat the public key as signer metadata owned by the account contract, not as the account identifier.

***

## Authority Management

### Ownership Pattern

LayerZero Starknet contracts use OpenZeppelin's `OwnableComponent`:

```rust wrap theme={null}
// Transfer ownership
fn transfer_ownership(ref self: ContractState, new_owner: ContractAddress) {
    self.ownable.transfer_ownership(new_owner);
}

// Renounce ownership (irreversible!)
fn renounce_ownership(ref self: ContractState) {
    self.ownable.renounce_ownership();
}
```

### Delegate Pattern

Set a delegate for configuration without transferring ownership:

```rust wrap theme={null}
// Set delegate via Endpoint
fn set_delegate(ref self: ContractState, delegate: ContractAddress) {
    let endpoint = IEndpointV2Dispatcher {
        contract_address: self.oapp_core.OAppCore_endpoint.read()
    };
    endpoint.set_delegate(delegate);
}
```

Delegates can:

* Set library configurations
* Update DVN settings
* Manage pathway configurations

Delegates cannot:

* Transfer ownership
* Set peers (owner only)

***

## Technical Constraints

### Contract Size

Starknet has contract size limits (see the [chain info cheat sheet](https://docs.starknet.io/learn/cheatsheets/chain-info) for current values):

| Metric                                | Limit           |
| ------------------------------------- | --------------- |
| Max contract bytecode size            | 81,920 felts    |
| Max contract class size (Sierra file) | 4,089,446 bytes |
| Contract classes per tx               | 1               |

**Mitigation**: Split large contracts into components or use libraries.

### Storage

| Constraint    | Details                          |
| ------------- | -------------------------------- |
| Storage key   | `felt252`                        |
| Storage value | `felt252`                        |
| Complex types | Serialized across multiple slots |

### Compute

| Resource | Notes                       |
| -------- | --------------------------- |
| Steps    | Varies by transaction type  |
| Builtins | Pedersen, Range Check, etc. |
| Memory   | Managed by Cairo VM         |

***

## Upgradeability

### Upgradeable Contracts

Use OpenZeppelin's `UpgradeableComponent`:

```rust wrap theme={null}
use openzeppelin::upgrades::UpgradeableComponent;

component!(path: UpgradeableComponent, storage: upgradeable, event: UpgradeableEvent);

#[external(v0)]
fn upgrade(ref self: ContractState, new_class_hash: ClassHash) {
    self.ownable.assert_only_owner();
    self.upgradeable.upgrade(new_class_hash);
}
```

### Upgrade Process

1. **Declare** new contract version
2. **Call** `upgrade(new_class_hash)` on existing contract
3. **Verify** new implementation

```bash theme={null}
# Declare new version
sncast declare --contract-name MyOFTv2

# Upgrade existing contract
sncast invoke \
  --contract-address <EXISTING_CONTRACT> \
  --function upgrade \
  --network sepolia \
  --arguments '<NEW_CLASS_HASH>'
```

<Warning>
  Ensure storage layout compatibility between versions!
</Warning>

***

## Common Commands Reference

### Scarb Commands

```bash theme={null}
scarb build          # Build contracts
scarb clean          # Clean build artifacts
scarb fmt            # Format code
scarb test           # Run Cairo tests (non-blockchain)
```

### snforge Commands

```bash theme={null}
snforge test                    # Run all tests
snforge test <name>             # Run specific test
snforge test -v                 # Verbose output
snforge test --coverage         # Generate coverage
```

### sncast Commands

```bash theme={null}
sncast account create           # Create new account
sncast account deploy           # Deploy account contract
sncast declare                  # Declare contract class
sncast deploy                   # Deploy contract instance
sncast invoke                   # Call external function
sncast call                     # Call view function
sncast tx-status <hash>         # Check transaction status
```

***

## Class Hash Mismatch Errors

When declaring contracts, you may encounter:

```
Error: Mismatch compiled class hash for class with hash 0x...
Actual: 0x..., Expected: 0x...
```

This error occurs when the CASM (Cairo Assembly) hash computed locally doesn't match what the network expects.

### Common Causes

| Cause                                 | Solution                                                    |
| ------------------------------------- | ----------------------------------------------------------- |
| **Scarb version mismatch**            | Use Scarb 2.14.0 (matches `starknet = "2.14.0"` dependency) |
| **Starknet Foundry version mismatch** | Use snfoundry 0.53.0 with Scarb 2.14.0                      |
| **Stale build artifacts**             | Run `scarb clean && scarb build` before declaring           |
| **RPC version incompatibility**       | Use RPC v0.9.0+ (see snfoundry.toml section above)          |

### Version Compatibility Matrix

| Scarb  | Cairo  | Starknet Foundry | RPC Version      |
| ------ | ------ | ---------------- | ---------------- |
| 2.14.0 | 2.14.0 | 0.53.0           | v0.9.0 - v0.10.0 |
| 2.13.1 | 2.13.1 | 0.49.0           | v0.9.0           |

<Tip>
  Always match your `starknet` dependency version in `Scarb.toml` with your installed Scarb version. Run `scarb --version` to check.
</Tip>

### Debugging Steps

1. **Verify versions match:**

   ```bash theme={null}
   scarb --version    # Should show 2.14.0
   sncast --version   # Should show 0.53.0
   ```

2. **Clean and rebuild:**

   ```bash theme={null}
   scarb clean
   rm -rf Scarb.lock
   scarb build
   ```

3. **Check Scarb.toml dependency:**

   ```toml theme={null}
   [dependencies]
   starknet = "2.14.0"  # Must match scarb version
   ```

4. **Verify RPC version:**
   ```bash theme={null}
   curl -X POST "<YOUR_RPC_URL>" \
     -H "Content-Type: application/json" \
     -d '{"jsonrpc":"2.0","method":"starknet_specVersion","params":[],"id":1}'
   # Should return "0.9.0" or "0.10.0"
   ```

***

## Next Steps

* [OApp Overview](/v2/developers/starknet/oapp/overview) - Building OApps
* [OFT Overview](/v2/developers/starknet/oft/overview) - Token transfers
* [Configuration Guide](/v2/developers/starknet/configuration/dvn-executor-config) - Security setup
* [Troubleshooting](/v2/developers/starknet/troubleshooting/common-errors) - Common errors
