Lux Standard

Fully Homomorphic Encryption (FHE)

Confidential computing with encrypted on-chain operations

Fully Homomorphic Encryption (FHE)

Complete FHE infrastructure for private on-chain computation. Perform arithmetic, comparisons, and logic on encrypted data without decryption.

Architecture Overview

┌─────────────────────────────────────────────────────────────────────────────────────────┐
│                            LUX FHE ARCHITECTURE                                         │
├─────────────────────────────────────────────────────────────────────────────────────────┤
│                                                                                         │
│  ENCRYPTED TYPES                                                                        │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐   │
│  │ ebool | euint8 | euint16 | euint32 | euint64 | euint128 | euint256 | eaddress  │   │
│  └─────────────────────────────────────────────────────────────────────────────────┘   │
│                                        │                                                │
│  ┌─────────────────────────────────────┼───────────────────────────────────────────┐   │
│  │                                     ▼                                            │   │
│  │  ┌─────────────────┐    ┌─────────────────────┐    ┌─────────────────────┐      │   │
│  │  │   FHE.sol       │    │    TaskManager      │    │     Gateway         │      │   │
│  │  │                 │    │                     │    │                     │      │   │
│  │  │ add, sub, mul   │───>│ 0xeA30...7848D9    │───>│ Decryption requests │      │   │
│  │  │ lt, gt, eq, ne  │    │ (Precompile)       │    │                     │      │   │
│  │  │ and, or, xor    │    │                     │    │                     │      │   │
│  │  │ select, cast    │    │                     │    │                     │      │   │
│  │  └─────────────────┘    └─────────────────────┘    └─────────────────────┘      │   │
│  │                                                                                  │   │
│  │  ACCESS CONTROL                                                                  │   │
│  │  ┌─────────────────────────────────────────────────────────────────────────┐    │   │
│  │  │ FHE.allow(ctHash, account)  - Grant read access to encrypted value      │    │   │
│  │  │ FHE.allowThis(ctHash)       - Grant contract read access                 │    │   │
│  │  │ FHE.isSenderAllowed(ct)     - Check if sender can use encrypted value   │    │   │
│  │  └─────────────────────────────────────────────────────────────────────────┘    │   │
│  └──────────────────────────────────────────────────────────────────────────────────┘   │
│                                                                                         │
│  PRECOMPILE ADDRESSES                                                                   │
│  ┌─────────────────────────────────────────────────────────────────────────────────┐   │
│  │ 0x0200...0080  FheOS         - Main FHE operations                              │   │
│  │ 0x0200...0081  ACL           - Access control list                              │   │
│  │ 0x0200...0082  InputVerifier - Verify encrypted inputs                          │   │
│  │ 0x0200...0083  Gateway       - Decryption gateway                               │   │
│  └─────────────────────────────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────────────────────────────┘

Core Contracts

ContractDescriptionImport
FHECore library - encrypted operations@luxfi/contracts/fhe/FHE.sol
TFHELow-level TFHE operations@luxfi/contracts/fhe/TFHE.sol
IFHEInterface definitions & precompile addresses@luxfi/contracts/fhe/IFHE.sol
GatewayDecryption request handling@luxfi/contracts/fhe/FHE.sol
GatewayCallerBase contract for decryption callbacks@luxfi/contracts/fhe/FHE.sol
PermissionedAccess control mixin@luxfi/contracts/fhe/access/Permissioned.sol
PermissionedV2Enhanced access control with EIP-712@luxfi/contracts/fhe/access/PermissionedV2.sol
FHEVMConfigFHEVM configuration@luxfi/contracts/fhe/config/FHEVMConfig.sol
GatewayConfigGateway configuration@luxfi/contracts/fhe/config/GatewayConfig.sol

Encrypted Types

type ebool is uint256;    // Encrypted boolean
type euint8 is uint256;   // Encrypted 8-bit unsigned integer
type euint16 is uint256;  // Encrypted 16-bit unsigned integer
type euint32 is uint256;  // Encrypted 32-bit unsigned integer
type euint64 is uint256;  // Encrypted 64-bit unsigned integer
type euint128 is uint256; // Encrypted 128-bit unsigned integer
type euint256 is uint256; // Encrypted 256-bit unsigned integer
type eaddress is uint256; // Encrypted address
type einput is bytes32;   // Encrypted input handle

Basic Operations

Arithmetic

import "@luxfi/contracts/fhe/FHE.sol";

contract ConfidentialMath {
    euint64 public encryptedValue;

    function add(euint64 a, euint64 b) public returns (euint64) {
        return FHE.add(a, b);
    }

    function sub(euint64 a, euint64 b) public returns (euint64) {
        return FHE.sub(a, b);
    }

    function mul(euint64 a, euint64 b) public returns (euint64) {
        return FHE.mul(a, b);
    }

    function div(euint64 a, euint64 b) public returns (euint64) {
        return FHE.div(a, b);
    }
}

Comparison

// Less than
ebool isLess = FHE.lt(a, b);

// Less than or equal (both lte and le work)
ebool isLessOrEqual = FHE.lte(a, b);

// Greater than
ebool isGreater = FHE.gt(a, b);

// Greater than or equal (both gte and ge work)
ebool isGreaterOrEqual = FHE.gte(a, b);

// Equal
ebool isEqual = FHE.eq(a, b);

// Not equal
ebool isNotEqual = FHE.ne(a, b);

// Min/Max
euint64 minimum = FHE.min(a, b);
euint64 maximum = FHE.max(a, b);

Bitwise Operations

// AND
euint64 andResult = FHE.and(a, b);

// OR
euint64 orResult = FHE.or(a, b);

// XOR
euint64 xorResult = FHE.xor(a, b);

// NOT
euint64 notResult = FHE.not(a);

// Shift left
euint64 shlResult = FHE.shl(a, b);

// Shift right
euint64 shrResult = FHE.shr(a, b);

// Rotate left
euint64 rolResult = FHE.rol(a, b);

// Rotate right
euint64 rorResult = FHE.ror(a, b);

Other Operations

// Square (more efficient than mul(a, a))
euint64 squared = FHE.square(a);

// Remainder
euint64 remainder = FHE.rem(a, b);

// Random number generation
euint64 randomValue = FHE.random();

Conditional (Select)

// Encrypted if-then-else
// If condition is true, return ifTrue, else return ifFalse
euint64 result = FHE.select(condition, ifTrue, ifFalse);

Access Control

FHE values require explicit access permissions:

import "@luxfi/contracts/fhe/FHE.sol";

contract AccessControlExample {
    mapping(address => euint64) private balances;

    function deposit(einput encryptedAmount, bytes calldata inputProof) external {
        euint64 amount = FHE.asEuint64(encryptedAmount, inputProof);

        // Grant this contract access to the encrypted value
        FHE.allowThis(amount);

        // Grant the depositor access to their balance
        FHE.allow(amount, msg.sender);

        balances[msg.sender] = FHE.add(balances[msg.sender], amount);
    }

    function checkBalance() external view returns (euint64) {
        // Only returns if sender is allowed
        require(FHE.isSenderAllowed(balances[msg.sender]), "Not allowed");
        return balances[msg.sender];
    }
}

Input Verification

Convert encrypted inputs to encrypted types:

// From encrypted input with proof
euint64 amount = FHE.asEuint64(encryptedInput, inputProof);

// From plaintext (trivial encryption)
euint64 plainValue = FHE.asEuint64(100);

// Type casting between encrypted types
euint32 smaller = FHE.asEuint32(FHE.asEuint64(value));

Confidential LRC20

LRC20 (Lux token standard) with encrypted balances:

import "@luxfi/contracts/fhe/token/LRC20/ConfidentialLRC20.sol";

contract PrivateToken is ConfidentialERC20 {
    constructor() ConfidentialERC20("Private Token", "PRIV") {
        _unsafeMint(msg.sender, 1000000);
    }

    // Balances are encrypted - only authorized parties can view
    // mapping(address => euint64) internal _balances;
}

ConfidentialLRC20 Functions

// Transfer with encrypted amount
function transfer(address to, einput encryptedAmount, bytes calldata inputProof)
    public returns (bool);

// Transfer with euint64 directly
function transfer(address to, euint64 amount) public returns (bool);

// Approve with encrypted amount
function approve(address spender, einput encryptedAmount, bytes calldata inputProof)
    public returns (bool);

// Get encrypted balance (requires permission)
function balanceOf(address account) public view returns (euint64);

Confidential Governance

Private voting with encrypted vote counts:

import "@luxfi/contracts/fhe/governance/ConfidentialGovernor.sol";
import "@luxfi/contracts/fhe/token/LRC20/ConfidentialLRC20.sol";

// Governance token with encrypted voting power
contract GovernanceToken is ConfidentialERC20Votes {
    // Vote counts are encrypted until tally
    // Prevents vote buying and coercion
}

// Governor with private voting
contract PrivateGovernor is ConfidentialGovernorAlpha {
    // Votes are encrypted during voting period
    // Only revealed after voting ends
}

Proposal Lifecycle

StateDescription
PendingProposal created, awaiting threshold verification
ActiveVoting in progress (encrypted votes)
SucceededQuorum reached, more FOR than AGAINST
DefeatedFailed to reach quorum or majority
QueuedPassed, in timelock queue
ExecutedProposal executed

Decryption

Request decryption of encrypted values using FHE.decrypt():

import "@luxfi/contracts/fhe/FHE.sol";
import "@luxfi/contracts/fhe/FHE.sol";

contract DecryptionExample is GatewayCaller {
    function decrypt(euint64 encryptedValue) external {
        // Request decryption via FHE library
        FHE.decrypt(encryptedValue);
    }

    // For callback-based decryption:
    function decryptAndCall(euint64 encryptedValue) external {
        uint256[] memory cts = new uint256[](1);
        cts[0] = euint64.unwrap(encryptedValue);

        TFHE.decrypt(
            cts,
            this.decryptionCallback.selector,
            0,  // msgValue
            block.timestamp + 100,  // maxTimestamp
            false  // passSignaturesToCaller
        );
    }

    function decryptionCallback(
        uint256 requestId,
        uint64 decryptedValue
    ) external onlyGateway {
        // Handle decrypted value
    }
}

Confidential Vesting

Vesting with encrypted amounts:

import "@luxfi/contracts/fhe/finance/ConfidentialVestingWallet.sol";

// Vesting wallet with private vesting amounts
contract PrivateVesting is ConfidentialVestingWallet {
    // Vesting amounts are encrypted
    // Only beneficiary can see their allocation
}

Token Contracts

ContractPathDescription
ConfidentialERC20token/ERC20/ConfidentialERC20.solLRC20 with encrypted balances
ConfidentialERC20Wrappedtoken/ERC20/ConfidentialERC20Wrapped.solWrap/unwrap standard LRC20 to encrypted
ConfidentialWETHtoken/ERC20/ConfidentialWETH.solWrapped LUX with encryption
ConfidentialERC20Mintabletoken/ERC20/extensions/ConfidentialERC20Mintable.solMintable confidential token
ConfidentialERC20WithErrorstoken/ERC20/extensions/ConfidentialERC20WithErrors.solConfidential token with error codes
ConfidentialERC20WithErrorsMintabletoken/ERC20/extensions/ConfidentialERC20WithErrorsMintable.solMintable token with error codes

Finance Contracts

ContractPathDescription
ConfidentialVestingWalletfinance/ConfidentialVestingWallet.solVesting with encrypted amounts
ConfidentialVestingWalletClifffinance/ConfidentialVestingWalletCliff.solVesting with cliff period

Utility Contracts

ContractPathDescription
EncryptedErrorsutils/EncryptedErrors.solError handling for FHE operations
TFHEErrorsutils/TFHEErrors.solTFHE-specific error definitions
EIP712access/EIP712.solEIP-712 typed data signing for FHE

EVM Version Requirement

FHE contracts require Cancun EVM for transient storage:

# foundry.toml
evm_version = "cancun"

Security Considerations

  1. Access Control: Always use FHE.allow() to grant access to encrypted values
  2. Input Verification: Verify encrypted inputs with proofs before use
  3. Decryption Timing: Decryption requests are async - design accordingly
  4. Gas Costs: FHE operations are more expensive than plaintext
  5. Side Channels: Avoid conditional logic that reveals encrypted values

Gas Costs (Approximate)

OperationGas Cost
Trivial Encrypt~50,000
Add/Sub~100,000
Multiply~150,000
Division/Remainder~200,000
Comparison (lt, gt, eq, etc.)~100,000
Bitwise (and, or, xor, not)~80,000
Shift/Rotate (shl, shr, rol, ror)~100,000
Min/Max~120,000
Select~120,000
Square~140,000
Random~150,000
Decrypt Request~200,000

Contract Directory Structure

contracts/fhe/
├── FHE.sol                 # Core FHE library
├── TFHE.sol                # Low-level TFHE operations
├── IFHE.sol                # Interface definitions
├── FheOS.sol               # FHE OS integration
├── ICofhe.sol              # Coprocessor interface
├── access/
│   ├── EIP712.sol          # EIP-712 signing
│   ├── Permissioned.sol    # Access control base
│   └── PermissionedV2.sol  # Enhanced access control
├── config/
│   ├── FHEVMConfig.sol     # FHEVM configuration
│   └── GatewayConfig.sol   # Gateway configuration
├── gateway/
│   ├── Gateway.sol         # Decryption gateway
│   └── GatewayCaller.sol   # Callback base contract
├── governance/
│   ├── ConfidentialGovernorAlpha.sol  # Private voting governor
│   ├── ConfidentialERC20Votes.sol     # Encrypted voting power
│   └── CompoundTimelock.sol           # Timelock controller
├── finance/
│   ├── ConfidentialVestingWallet.sol      # Encrypted vesting
│   └── ConfidentialVestingWalletCliff.sol # Vesting with cliff
├── token/ERC20/
│   ├── ConfidentialERC20.sol          # Base confidential token
│   ├── ConfidentialERC20Wrapped.sol   # Wrap/unwrap support
│   ├── ConfidentialWETH.sol           # Wrapped native token
│   └── extensions/
│       ├── ConfidentialERC20Mintable.sol
│       ├── ConfidentialERC20WithErrors.sol
│       └── ConfidentialERC20WithErrorsMintable.sol
└── utils/
    ├── EncryptedErrors.sol   # Error handling
    ├── TFHEErrors.sol        # TFHE errors
    └── debug/
        ├── Console.sol       # Debug logging
        └── MockFheOps.sol    # Testing mock

On this page