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

# Sui Development Guidance

> Technical reference for Sui Development Guidance. Complete API documentation with functions, parameters, and usage examples. LayerZero enables secure...

This page provides development guidance for building LayerZero applications on Sui, covering toolchain setup, operational practices, and technical constraints.

## Toolchain Setup

### Sui CLI

**Tested Version**: `sui@v1.54.1`

Install the [Sui CLI](https://docs.sui.io/references/cli):

```bash wrap theme={null}
cargo install --locked --git https://github.com/MystenLabs/sui.git --branch mainnet sui
```

Verify installation:

```bash wrap theme={null}
sui --version
# sui 1.54.1-...
```

### Project Structure

Typical Sui Move project structure:

```
my-oapp/
├── Move.toml              # Package manifest
├── sources/
│   ├── oapp.move         # Main OApp logic
│   ├── config.move       # Configuration
│   └── ...
├── tests/
│   └── oapp_tests.move   # Unit tests
└── scripts/
    └── deploy.sh         # Deployment scripts
```

### Move.toml Configuration

For [package structure](https://docs.sui.io/concepts/sui-move-concepts/packages) details:

```toml wrap theme={null}
[package]
name = "my_oapp"
version = "0.0.1"

[dependencies]
Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet" }
LayerZeroEndpoint = { git = "https://github.com/LayerZero-Labs/LayerZero-v2.git", subdir = "packages/layerzero-v2/sui/contracts/endpoint-v2", rev = "main" }
LayerZeroOApp = { git = "https://github.com/LayerZero-Labs/LayerZero-v2.git", subdir = "packages/layerzero-v2/sui/contracts/oapps/oapp", rev = "main" }

[addresses]
my_oapp = "0x0"
sui = "0x2"
```

## Package Verification

Sui supports package verification via [SuiScan](https://suiscan.xyz):

### Verification Methods

1. **Source Upload**: Upload source code directly to SuiScan
2. **API Verification**: Use SuiScan's API for programmatic verification

### Verification via SuiScan

1. Navigate to [https://suiscan.xyz/mainnet/package-verification](https://suiscan.xyz/mainnet/package-verification)
2. Enter your package address
3. Upload source files
4. Wait for verification

### Verification via API

```bash wrap theme={null}
curl -X POST https://suiscan.xyz/api/verify \
  -H "Content-Type: application/json" \
  -d '{
    "packageId": "0x...",
    "sourceCode": "...",
    "network": "mainnet"
  }'
```

## Development Environment

### Building Contracts

```bash wrap theme={null}
sui move build
```

### Running Tests

```bash wrap theme={null}
sui move test
```

### Local Development

Start a local Sui network:

```bash wrap theme={null}
sui start
```

## Deployment

### Deploying to Testnet

```bash wrap theme={null}
sui client publish \
    --gas-budget 100000000 \
    --json
```

### Deploying to Mainnet

```bash wrap theme={null}
sui client switch --env mainnet
sui client publish \
    --gas-budget 100000000 \
    --json
```

### Deployment Script Example

```bash wrap theme={null}
#!/bin/bash

# Build
echo "Building..."
sui move build

# Deploy
echo "Deploying..."
RESULT=$(sui client publish \
    --gas-budget 100000000 \
    --json)

# Extract package ID
PACKAGE_ID=$(echo $RESULT | jq -r '.objectChanges[] | select(.type=="published") | .packageId')

echo "Package ID: $PACKAGE_ID"

# Save to file
echo $PACKAGE_ID > deployed_package.txt
```

## Operational Practices

### Package Upgrades

Sui packages are immutable by default but can be made [upgradeable](https://docs.sui.io/concepts/sui-move-concepts/packages/upgrade).

**[`UpgradeCap`](https://docs.sui.io/concepts/sui-move-concepts/packages/upgrade)**: Owned object granting upgrade authority

```rust wrap theme={null}
/// Automatically created when publishing with --with-unpublished-dependencies
public struct UpgradeCap has key, store {
    id: UID,
    package: ID,     // Package being controlled
    version: u64,    // Current version
    policy: u8,      // Upgrade policy (compatible, additive, dep_only)
}
```

**Transfer Upgrade Authority**:

```bash wrap theme={null}
sui client transfer \
    --to <NEW_OWNER_ADDRESS> \
    --object-id <UPGRADE_CAP_OBJECT_ID> \
    --gas-budget 10000000
```

**Upgrade a Package**:

```bash wrap theme={null}
sui client upgrade \
    --upgrade-capability <UPGRADE_CAP_OBJECT_ID> \
    --gas-budget 200000000
```

**Key Point**: Upgraded packages maintain compatibility with objects created by previous versions, provided you follow Sui's upgrade policies.

### Capability Management

LayerZero uses multiple capability objects:

**For OApp/OFT Packages**:

* `CallCap`: Authorizes creating `Call` objects (usually stored in package module)
* `AdminCap`: Authorizes admin operations (transfer to new admin as needed)
* `MigrationCap`: Authorizes migrating OApp/OFT to new implementations (store securely)
* `TreasuryCap<T>`: Authorizes minting/burning coins (for OFT mint/burn type)
* `UpgradeCap`: Authorizes package upgrades (transfer with caution)

**Transfer Pattern**:

```rust wrap theme={null}
// Transfer owned object to new owner
transfer::public_transfer(admin_cap, new_admin_address);
```

**No Safe Transfer**: Sui doesn't have EVM's `safeTransfer` callback. Transfers are direct:

```rust wrap theme={null}
transfer::public_transfer(object, recipient);  // Direct, no callback
```

### Multisig Patterns

For multi-party control, use:

1. **Sui Multisig Addresses**: Native 1-of-n or k-of-n multisig
2. **Shared Control Objects**: Create a shared configuration object requiring multiple approvals
3. **Third-Party Solutions**: Sui Wallet multisig, protocol-specific multisig

**Example using address derivation**:

```bash wrap theme={null}
# Create multisig address with multiple public keys
sui keygen multi-sig \
    --pks <PUBKEY1> <PUBKEY2> <PUBKEY3> \
    --weights 1 1 1 \
    --threshold 2
```

## Resource & Fee Models

See [Sui Gas Model](https://docs.sui.io/concepts/tokenomics/gas-in-sui) for complete details.

### Storage Gas

Charged for storing data onchain:

```rust wrap theme={null}
// Creating objects costs storage gas
let obj = MyObject { id: object::new(ctx), data: ... };
transfer::share_object(obj); // Storage charged here
```

### Computation Gas

Charged for execution:

```rust wrap theme={null}
// Complex logic costs computation gas
public fun complex_operation(...) {
    // Each instruction consumes gas
    let result = heavy_computation();
    // ...
}
```

### Rebate Mechanism

When storage is freed, gas is refunded:

```rust wrap theme={null}
// Deleting objects triggers rebate
let MyObject { id, data } = obj;
object::delete(id); // Storage rebate issued
```

**Important**: This can result in **negative gas utilization** for net storage reduction.

### Base Budget

Every transaction requires a minimum of **1000 gas units**, even if net cost is negative due to rebates.

## Technical Constraints

### Package Size Limit

**Maximum size per package**: 250 KiB

If your package exceeds this:

* Split into multiple packages
* Reduce unused code
* Optimize data structures

### Transaction Size Constraints

See [Sui Transaction Limits](https://move-book.com/guides/building-against-limits/):

* Max objects per transaction: 256
* Max events per transaction: 1024
* Max argument size: 128 KB

### Compute Limits

Gas limits vary by network:

* **Testnet**: Lower limits
* **Mainnet**: Higher limits

For LayerZero operations, budget at least:

* **Simple send**: 5,000,000 gas
* **Complex send**: 20,000,000 gas
* **Receive**: 10,000,000 gas

### Network Resource Limits

Monitor these limits:

* **Object count per address**: Unlimited, but impacts query performance
* **Storage per address**: Unlimited, but costs scale linearly
* **Transaction throughput**: \~5,000 TPS (network-wide)

## Network Considerations

### Finality

Sui uses a **checkpoint-based finality** system:

* **Soft finality**: Certificate of transaction (milliseconds)
* **Hard finality**: Checkpoint inclusion (\~2-3 seconds)

For LayerZero verification, DVNs wait for checkpoint finality.

### RPC Infrastructure

**Public RPCs**:

* Mainnet: `https://fullnode.mainnet.sui.io:443`
* Testnet: `https://fullnode.testnet.sui.io:443`
* Devnet: `https://fullnode.devnet.sui.io:443`

**Private RPC Providers**:

* Ankr
* QuickNode
* Blast API

For production, use private RPCs for better reliability and rate limits.

## Channel Management

### Recovery Methods

LayerZero provides recovery methods for stuck messages:

```rust wrap theme={null}
// Skip a message
public entry fun skip(
    oapp: &mut OApp,
    admin_cap: &AdminCap,
    src_eid: u32,
    sender: vector<u8>,
    nonce: u64,
)

// Clear a message
public entry fun clear(
    oapp: &mut OApp,
    admin_cap: &AdminCap,
    src_eid: u32,
    sender: vector<u8>,
    nonce: u64,
)

// Nilify a message
public entry fun nilify(
    oapp: &mut OApp,
    admin_cap: &AdminCap,
    src_eid: u32,
    sender: vector<u8>,
    nonce: u64,
)
```

**Authorization**: All recovery methods require the `AdminCap` object.

### Querying State with TypeScript SDKs

The Sui CLI has limitations for querying state. Use TypeScript SDKs instead:

```typescript wrap theme={null}
import {SuiClient} from '@mysten/sui.js/client';
import {OApp} from '@layerzerolabs/lz-sui-sdk-v2';

const client = new SuiClient({url: 'https://fullnode.mainnet.sui.io:443'});

// Query peer configuration
const peer = await oapp.getPeer(client, 30101);

// Query nonce
const nonce = await oapp.getInboundNonce(client, 30101, senderBytes32);

// Query configuration
const config = await oapp.getConfig(client, 30101);
```

### Sui CLI Limitations

The Sui CLI cannot easily:

* Parse complex return values from view functions
* Handle nested data structures
* Decode bytes arrays

**Workaround**: Use the TypeScript SDK for all state queries.

## Best Practices

### 1. Test Thoroughly

```bash wrap theme={null}
# Run unit tests
sui move test

# Run integration tests on testnet
sui client call --package $PKG ... --json
```

### 2. Monitor Gas Usage

```bash wrap theme={null}
# Use --gas-budget appropriately
sui client call \
    --gas-budget 20000000 \ # Start higher
    --json
```

### 3. Handle Rebates Correctly

```rust wrap theme={null}
// Don't assume gas cost is always positive
// Rebates can make net cost negative
```

### 4. Version Your Packages

```toml wrap theme={null}
[package]
name = "my_oapp"
version = "1.0.0" # Increment on upgrades
```

### 5. Secure Your Keys

```bash wrap theme={null}
# Use hardware wallets for mainnet
# Keep upgrade capabilities secure
# Use multisig for critical operations
```

## Common Gotchas

### 1. Negative Gas Utilization

When storage is freed, transactions can have negative net gas cost. Budget at least 1000 base units.

### 2. Package Size Exceeded

**Error**: `Package size exceeds maximum`

**Solution**: Split into multiple packages or optimize code.

### 3. Object Ownership Errors

**Error**: `Invalid object ownership`

**Solution**: Verify object is owned by signer or is shared.

### 4. Insufficient Gas

**Error**: `Insufficient gas`

**Solution**: Increase `--gas-budget` parameter.

## Additional Resources

* [Sui Documentation](https://docs.sui.io/)
* [Sui Move Book](https://move-book.com/)
* [Sui GitHub](https://github.com/MystenLabs/sui)
* [LayerZero Sui Contracts](https://github.com/LayerZero-Labs/LayerZero-v2/tree/main/packages/layerzero-v2/sui)

## Next Steps

* [OApp Overview](/v2/developers/sui/oapp/overview)
* [OFT Overview](/v2/developers/sui/oft/overview)
* [Configuration Guide](/v2/developers/sui/configuration/dvn-executor-config)
* [Troubleshooting](/v2/developers/sui/troubleshooting/common-errors)
