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

# Best Practices

> Key best practices for developing secure and efficient FHE smart contracts with CoFHE

## Overview

This guide outlines key best practices for developing with CoFHE, based on recommendations from our development team. Following these practices will help you build secure, efficient, and maintainable FHE-enabled smart contracts.

## Prerequisites

Before reading this guide, you should:

* Have completed the [Quick Start](/fhe-library/introduction/quick-start) setup
* Understand basic FHE concepts and encrypted types
* Be familiar with Solidity smart contract development

## Security Considerations

### Publish Decrypted Data Carefully

Decryption is a multi-step process: the client requests a plaintext + signature off-chain via `decryptForTx`, then publishes or verifies the result on-chain using `FHE.publishDecryptResult` or `FHE.verifyDecryptResult`. Once published, the plaintext is visible to everyone on the blockchain.

**Key principles:**

* **Evaluate information leakage**: Before publishing a decrypted value on-chain, consider what information you're exposing and what an observer might learn from it
* **Minimize published values**: Only publish decrypted results when your protocol truly requires the plaintext on-chain. Use `decryptForView` if you only need to display the value in a UI
* **Use `verifyDecryptResult` when possible**: If your contract only needs to confirm a value without storing it publicly, prefer `FHE.verifyDecryptResult` over `FHE.publishDecryptResult`

<Warning>
  Publishing a decrypted value on-chain makes it permanently visible to all observers. Always consider whether you need `decryptForTx` (on-chain proof) or `decryptForView` (UI-only) for your use case.
</Warning>

### Always update permissions

Remember to call `FHE.allowThis()` after modifying any encrypted value that needs to be accessed later:

```solidity theme={null}
counter = FHE.add(counter, FHE.asEuint32(1));
FHE.allowThis(counter);
```

<Note>
  Without calling `FHE.allowThis()`, your contract won't be able to access the encrypted value in subsequent operations. This is a common source of errors in FHE development.
</Note>

### Avoid code branching based on encrypted data

**Remember: there is no secure code branching with FHE.** Decrypting to make branching decisions is generally a bad practice and can leak information.

**Best practices:**

* **Use constant-time algorithms**: Design your code to follow the same execution path regardless of encrypted values
* **Prefer FHE.select over conditional logic**: Use built-in selection operations rather than decrypting for if/else decisions

**Example:**

<CodeGroup>
  ```solidity Don't Do This theme={null}
  // Don't reveal encrypted values to make branching decisions
  FHE.publishDecryptResult(condition, plaintext, signature);
  if (plaintext > 0) {
      result = a;
  } else {
      result = b;
  }
  ```

  ```solidity Recommended Approach theme={null}
  // Use FHE.select instead
  result = FHE.select(condition, a, b);
  ```
</CodeGroup>

<Tip>
  Since conditional branching doesn't work with encrypted values, always use `FHE.select()` for conditional logic. This ensures your code follows a constant execution path regardless of the encrypted values.
</Tip>

## Performance Optimization

### Optimize computational efficiency

FHE operations are computationally expensive. Optimize your contracts to minimize overhead:

**Key strategies:**

* **Minimize FHE operations**: Each operation adds computational overhead, so reduce the number of operations where possible
* **Use the minimum bit-width necessary**: Choose the smallest integer type that can safely represent your data

<CodeGroup>
  ```solidity ❌ Less Efficient theme={null}
  euint64 counter;  // Using 64 bits when 32 would suffice
  ```

  ```solidity ✅ More Efficient theme={null}
  euint32 counter;  // Using 32 bits when that's sufficient
  ```
</CodeGroup>

### Reuse Encrypted Constants

Encrypt constant values once and reuse them to save gas:

```solidity theme={null}
// Good practice: Encrypt once, reuse many times
euint32 ONE = FHE.asEuint32(1);
FHE.allowThis(ONE);

// Later in the code
counter = FHE.add(counter, ONE);
counter = FHE.add(counter, ONE);  // Reusing the same encrypted constant
```

<Tip>
  Reusing encrypted constants is a gas optimization technique. Encrypt frequently used values (like 0, 1, or common thresholds) once at contract initialization and reuse them throughout your contract's lifetime.
</Tip>

### Plan for Asynchronous Operations

CoFHE operations are asynchronous by nature. Design your application to handle this gracefully:

**UI considerations:**

* **Implement loading indicators**: Show spinners, progress bars, or status messages to inform users when operations are in progress
* **Use progress indicators**: Provide feedback during encryption and decryption operations
* **Consider state management**: Design your application to handle pending states gracefully

**Example UI pattern:**

Use `.onStep(callback)` to track encryption progress. The callback fires at the start and end of each step, receiving the current `EncryptStep` enum value and a context object with `isStart`, `isEnd`, and `duration` (milliseconds, only meaningful on `isEnd`).

```typescript theme={null}
import { createCofheClient, createCofheConfig } from '@cofhe/sdk/web';
import { Encryptable, EncryptStep } from '@cofhe/sdk';
import { chains } from '@cofhe/sdk/chains';

const [isEncrypting, setIsEncrypting] = useState(false);
const [currentStep, setCurrentStep] = useState<string | null>(null);

const handleEncrypt = async () => {
  setIsEncrypting(true);
  try {
    const result = await cofheClient
      .encryptInputs([Encryptable.uint32(5n)])
      .onStep((step, ctx) => {
        if (ctx?.isStart) setCurrentStep(step);
        if (ctx?.isEnd) console.log(`${step} done in ${ctx.duration}ms`);
      })
      .execute();
    // Handle result
  } finally {
    setIsEncrypting(false);
    setCurrentStep(null);
  }
};
```

The `EncryptStep` enum values fire in order: `InitTfhe` → `FetchKeys` → `Pack` → `Prove` → `Verify`.

<Info>
  CoFHE operations may take time to complete, especially on testnets. Always provide user feedback during these operations to improve user experience.
</Info>

## Development Workflow

### Start with Mock Environment

Begin development using mock contracts for faster iteration:

* **Faster feedback loop**: Mock environment provides immediate results without network delays
* **Easier debugging**: Plaintext values are visible in mock contracts, making debugging simpler
* **No external dependencies**: Test locally without connecting to testnets

### Test Thoroughly

Write comprehensive tests covering:

* **Both environments**: Test in mock and testnet environments
* **Edge cases**: Handle zero values, maximum values, and boundary conditions
* **Error scenarios**: Test what happens when operations fail or permissions are missing

### Gas Optimization

Be aware of gas costs:

* **Mock environments simulate higher costs**: Gas costs in mock environments are higher than production
* **Test on testnet for accurate estimates**: Always test gas consumption on testnet before deployment
* **Optimize before deployment**: Review and optimize your contract's gas usage

## Summary

Following these best practices will help you:

* **Build secure contracts**: Proper permission management and avoiding information leakage
* **Optimize performance**: Minimize operations and reuse encrypted constants
* **Improve user experience**: Handle asynchronous operations gracefully
* **Develop efficiently**: Use mock environments for rapid iteration

<Check>
  By following these best practices, you'll create more secure, efficient, and maintainable FHE-enabled smart contracts.
</Check>

## Next Steps

* Learn about [encrypted data types](/fhe-library) and their use cases
* Explore [FHE operations](/fhe-library) available in the library
* Review [access control mechanisms](/fhe-library) for managing permissions
* Check out [common pitfalls](/fhe-library) to avoid
