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

# Control Flow

> Conditional logic with encrypted values

# Control Flow

The `e_select` function enables conditional logic on encrypted values without revealing the condition.

## e\_select

```rust theme={null}
e_select(condition: Ebool, if_true: Euint128, if_false: Euint128) -> Euint128
```

Returns `if_true` when condition is encrypted true, `if_false` otherwise.

## Example: Confidential Transfer with Balance Check

```rust theme={null}
pub fn confidential_transfer(
    ctx: Context<Transfer>,
    transfer_amount: Euint128,
) -> Result<()> {
    let inco = ctx.accounts.inco_lightning_program.to_account_info();
    let signer = ctx.accounts.authority.to_account_info();

    let source_balance = ctx.accounts.source.balance;
    let dest_balance = ctx.accounts.destination.balance;

    // Check if source has sufficient balance (encrypted comparison)
    let cpi_ctx = CpiContext::new(inco.clone(), Operation { signer: signer.clone() });
    let has_sufficient: Ebool = e_ge(cpi_ctx, source_balance, transfer_amount, 0)?;

    // Create zero for failed transfer case
    let zero = Euint128::wrap(0);

    // Select actual transfer amount: if sufficient balance, use amount; else use 0
    let cpi_ctx = CpiContext::new(inco.clone(), Operation { signer: signer.clone() });
    let actual_amount: Euint128 = e_select(cpi_ctx, has_sufficient, transfer_amount, zero, 0)?;

    // Subtract from source (will subtract 0 if insufficient)
    let cpi_ctx = CpiContext::new(inco.clone(), Operation { signer: signer.clone() });
    let new_source_balance: Euint128 = e_sub(cpi_ctx, source_balance, actual_amount, 0)?;

    // Add to destination (will add 0 if insufficient)
    let cpi_ctx = CpiContext::new(inco.clone(), Operation { signer: signer.clone() });
    let new_dest_balance: Euint128 = e_add(cpi_ctx, dest_balance, actual_amount, 0)?;

    // Update balances
    ctx.accounts.source.balance = new_source_balance;
    ctx.accounts.destination.balance = new_dest_balance;

    Ok(())
}
```

## How e\_select Works

```mermaid theme={null}
flowchart TD
    subgraph Inputs["Encrypted Inputs"]
        A[("🔒 Condition<br/>(Ebool)")]
        B[("🔒 if_true<br/>(Euint128)")]
        C[("🔒 if_false<br/>(Euint128)")]
    end

    subgraph TEE["Covalidator (TEE)"]
        D{{"e_select"}}
        E["Decrypt → Evaluate → Re-encrypt<br/>inside secure enclave"]
    end

    subgraph Output["Encrypted Output"]
        F[("🔒 Result<br/>(Euint128)")]
    end

    A --> D
    B --> D
    C --> D
    D --> E
    E --> F

    style A fill:#ff6b6b,color:#fff
    style B fill:#4ecdc4,color:#fff
    style C fill:#45b7d1,color:#fff
    style F fill:#96ceb4,color:#fff
    style D fill:#667eea,color:#fff
    style E fill:#764ba2,color:#fff
```

### Conditional Transfer Flow

```mermaid theme={null}
sequenceDiagram
    participant User
    participant Program as Solana Program
    participant TEE as Inco Lightning<br/>(Covalidator TEE)

    User->>Program: transfer(encrypted_amount)

    Note over Program: source_balance, dest_balance<br/>are encrypted handles

    Program->>TEE: e_ge(source_balance, amount)
    TEE-->>Program: has_sufficient (Ebool)

    Program->>TEE: e_select(has_sufficient, amount, zero)
    TEE-->>Program: actual_amount (Euint128)

    Note over TEE: If sufficient: actual = amount<br/>If not: actual = 0<br/>(evaluated securely in TEE)

    Program->>TEE: e_sub(source_balance, actual_amount)
    TEE-->>Program: new_source_balance

    Program->>TEE: e_add(dest_balance, actual_amount)
    TEE-->>Program: new_dest_balance

    Program->>Program: Update account balances
    Program-->>User: Transaction complete

    Note over User,TEE: No party learns if transfer<br/>succeeded or failed!
```

***

## Why Use e\_select?

This pattern ensures:

* **No information leakage**: Balance check happens on encrypted values
* **Atomic transfers**: Either full amount transfers or nothing
* **No negative balances**: Impossible to overdraw

<Warning>
  Never branch on decrypted values in your program. Use `e_select` to keep logic encrypted:

  ```rust theme={null}
  // BAD: Leaks information through control flow
  if decrypted_balance > amount {
      transfer(amount);
  }

  // GOOD: Encrypted conditional
  let sufficient = e_ge(ctx, balance, amount, 0)?;
  let actual = e_select(ctx, sufficient, amount, zero, 0)?;
  e_sub(ctx, balance, actual, 0)?;
  ```
</Warning>

<Note>
  The last parameter in operation calls identifies whether the left-hand side operand is ciphertext (`0`) or plaintext (`1`). Always pass `0` when working with encrypted handles.
</Note>
