Think·two-phase async

FHE Inference

Encrypted ML

Run inference on CKKS-encrypted tensors. Plaintext never leaves the user.

0x0000000000000000000000000000000000000807Explorer
CKKS encryption. Encrypt input client-side (e.g. tfhe-rs WASM, node-seal). Plaintext never touches the chain. Output is also encrypted — only key holder decrypts.
click 'auto' (capability = 10)
hex bytes (CKKS ciphertext)
hex bytes (StorageRef)
≤ 500
min escrow: 0.1000 RITUALyou have: RITUAL
Connect your wallet to submit a real transaction.
to: 0x0000000000000000000000000000000000000807chainId 1979 · two-phase · 19 fields
Output
Click Validate to encode the FHE inference request.
Plaintext never reaches the chain.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {PrecompileConsumer} from "./utils/PrecompileConsumer.sol";

contract FHEInferenceConsumer is PrecompileConsumer {
    address constant FHE = address(0x807);
    address constant ASYNC_DELIVERY = 0x5A16214fF555848411544b005f7Ac063742f39F6;

    event FHERequested(bytes32 indexed jobId);
    event FHEDelivered(bytes32 indexed jobId, bytes encryptedOutput);

    /// @notice Run FHE inference on CKKS-encrypted input. The plaintext
    /// never touches the chain — only the encrypted ciphertext does.
    /// Decryption happens off-chain with the user's secret key.
    function infer(address executor, bytes calldata encryptedInput, bytes calldata evkRef) external {
        bytes memory encoded = abi.encode(
            executor,
            new bytes[](0), uint256(500), new bytes[](0), bytes(""),
            "ckks/mnist-classifier-3-layer",
            encryptedInput, bytes(""), evkRef,
            uint8(3),                            // numLayers
            uint64(block.number + 5000),        // maxInferenceBlock
            address(this), this.onFHEResult.selector,
            uint256(500_000), uint256(1_000_000_000),
            uint256(100_000_000), uint256(0),
            bytes(""), bytes("")
        );
        (bool ok,) = FHE.call(encoded);
        require(ok, "fhe call failed");
    }

    function onFHEResult(bytes32 jobId, bytes calldata encryptedOutput) external {
        require(msg.sender == ASYNC_DELIVERY, "unauth");
        // Encrypted output — only the key holder can decrypt off-chain.
        emit FHEDelivered(jobId, encryptedOutput);
    }
}