finmath decryption oracle


⚠️ Before you continue: Please read the Disclaimer.
By using this site, software, or contracts, you acknowledge that you have read and accepted it.


NPM Package

The canonical decryption oracle proxy contract and callback interfaces are published via npm at @finmath.net/dvp@0.8.0. The local interfaces below have the same declarations, ABI, and NatSpec as that package. Their declarations are ordered generate, verify, decrypt for readability.

IKeyDecryptionOracle - Interface of the Decryption Oracle Contract

You find the current version of IKeyDecryptionOracle in src/main/solidity.

// SPDX-License-Identifier: CC0-1.0
pragma solidity >=0.8.0 <0.9.0;

import "./IKeyDecryptionOracleCallback.sol";

/*------------------------------------------- DESCRIPTION ------------------------------------------------------------*/

/**
 * @title ERC-7573 Decryption Oracle Contract - a bridge to an external decryption oracle.
 * @dev Interface specification for a smart contract that performs decryption (by bridging to an external oracle).
 * @author Christian Fries.
 * @notice See documentation for details.
 *
 * Semantics note (best-effort routing):
 * Implementations MAY attempt the callback in a best-effort fashion and MUST NOT assume that
 * callback execution success is equivalent to tx success (`receipt.status == 1`).
 * Implementations SHOULD provide an explicit on-chain signal of callback outcome (e.g. CallbackSucceeded/CallbackFailed events).
 *
 * Request correlation:
 * Each request method MUST allocate and return a requestId that is unique within the oracle proxy.
 * The proxy MUST pass that requestId to the callback. The caller-supplied id is consumer context
 * retained in the request event; it is not the callback correlation identifier.
 * Request methods MUST return before attempting the corresponding callback.
 * Before invoking a callback, the proxy MUST make that request unavailable to another fulfillment.
 * A best-effort implementation MAY restore it to pending after a failed callback so it can be retried.
 */
interface IKeyDecryptionOracle {
    /**
     * @dev One key reference requested for verification and its semantic role. Despite the
     * historical name, encryptedKey MAY be publicly readable authenticated external-settlement
     * metadata; possession of it MUST NOT itself authorize release of the underlying key.
     */
    struct EncryptedKey {
        bytes32 keyId;
        bytes encryptedKey;
    }

    /*------------------------------------------- EVENTS -------------------------------------------------------------*/

    /**
     * @dev Emitted when encrypted key generation is requested (issued by requestGenerateEncryptedHashedKeys).
     * @param sender The requester (msg.sender) that issued the request.
     * @param id Consumer-defined context emitted with the request.
     * @param callback Callback contract to be invoked on fulfillment.
     * @param receiverContract Contract that is eligible to request decryption.
     * @param transaction Transaction specification to be verified against the key.
     * @param keyIds Unique semantic identifiers for the keys to generate.
     * @param requestId Correlation id for the fulfillment.
     */
    event EncryptedHashedKeysGenerationRequested(
        address indexed sender,
        uint256 id,
        IKeyDecryptionOracleCallback indexed callback,
        address receiverContract,
        bytes transaction,
        bytes32[] keyIds,
        uint256 indexed requestId
    );

    /**
     * @dev Emitted when atomic verification of an encrypted-key batch is requested
     * (issued by requestVerifyEncryptedKeys).
     * @param sender The requester (msg.sender) that issued the request.
     * @param id Consumer-defined context emitted with the request.
     * @param keys Complete role-tagged encrypted-key set to verify.
     * @param callback Receiver of the verification result.
     * @param requestId Correlation id for the fulfillment.
     */
    event EncryptedKeysVerificationRequested(
        address indexed sender,
        uint256 id,
        EncryptedKey[] keys,
        IKeyDecryptionOracleCallback indexed callback,
        uint256 indexed requestId
    );

    /**
     * @dev Emitted when a decryption is requested (issued by requestDecrypt).
     * @param sender The requester (msg.sender) that issued the request.
     * @param id Consumer-defined context emitted with the request.
     * @param encryptedKey Encryption of a key for which decryption is requested.
     * @param callback Callback contract to be invoked on fulfillment.
     * @param transaction Transaction specification to be verified against the key.
     * @param requestId Correlation id for the fulfillment.
     */
    event DecryptionRequested(
        address indexed sender,
        uint256 id,
        bytes encryptedKey,
        IKeyDecryptionOracleCallback indexed callback,
        bytes transaction,
        uint256 indexed requestId
    );

    /**
     * @dev Optional but recommended: emitted by the oracle proxy after attempting the callback.
     * Off-chain services SHOULD use these events to decide whether a fulfillment needs retry.
     *
     * selector identifies which callback method was attempted.
     */
    event CallbackSucceeded(
        uint256 indexed requestId,
        address indexed callback,
        bytes4 indexed selector,
        uint256 consumerId
    );

    /**
     * @dev Optional but recommended: emitted by the oracle proxy after attempting the callback.
     * Off-chain services SHOULD use these events to decide whether a fulfillment needs retry.
     *
     * selector identifies which callback method was attempted. reason contains
     * callback revert/return data when available and can be empty (for example, on OOG).
     */
    event CallbackFailed(
        uint256 indexed requestId,
        address indexed callback,
        bytes4 indexed selector,
        uint256 consumerId,
        bytes reason
    );

    /*------------------------------------------- FUNCTIONALITY: REQUESTS --------------------------------------------*/

    /**
     * @notice Generates a batch of encrypted keys and hashes internally associated with the given
     * contract (receiverContract) and transaction. The generated keys are passed to the callback contract.
     *
     * @dev Emits an {EncryptedHashedKeysGenerationRequested} event.
     * Implementations MUST reject an empty `keyIds` array and duplicate identifiers and MUST
     * impose a documented finite maximum batch size. Every generated reference MUST authenticate
     * its keyId and a common one-use settlement context bound to the requesting contract, `id`,
     * and the full generation context.
     * @param id Consumer-defined context emitted with the request.
     * @param callback The callback contract.
     * @param receiverContract Contract that is eligible to receive the decryption.
     * @param transaction General purpose transaction identifier.
     * @param keyIds Unique semantic identifiers for the keys to generate. A single-element batch is valid.
     * @return requestId Oracle-assigned correlation identifier passed to the callback.
     */
    function requestGenerateEncryptedHashedKeys(
        uint256 id,
        IKeyDecryptionOracleCallback callback,
        address receiverContract,
        bytes calldata transaction,
        bytes32[] calldata keyIds
    ) external payable returns (uint256 requestId);

    /**
     * @notice Performs atomic verification of a role-tagged encrypted-key batch. The oracle
     * extracts the common receiver and transaction and calculates each decrypted key's hash,
     * without exposing any decrypted key.
     *
     * @dev Emits an {EncryptedKeysVerificationRequested} event. Implementations MUST reject
     * an empty batch, duplicate keyIds and empty encrypted keys, and MUST impose a documented
     * finite maximum batch size. A single-element batch is valid. Array order has no semantic meaning.
     * The proxy MUST retain or commit to the exact requested `(keyId, encryptedKey)` set so a
     * fulfillment cannot substitute, omit or add a key. Every reference MUST authenticate its
     * keyId and the same one-use settlement context, and that context MUST match this request's
     * id and stored consumer context.
     * @param id Consumer-defined context emitted with the request.
     * @param keys Complete role-tagged encrypted-key set to verify.
     * @param callback The callback contract.
     * @return requestId Oracle-assigned correlation identifier passed to the callback.
     */
    function requestVerifyEncryptedKeys(
        uint256 id,
        EncryptedKey[] calldata keys,
        IKeyDecryptionOracleCallback callback
    ) external payable returns (uint256 requestId);

    /**
     * @notice Performs a decryption of the given encryptedKey if and only if the caller is allowed to perform this request.
     * The decrypted key is passed to the callback contract's onKeyReleased function, if and only if
     * the callback and the given transaction argument validate against the specification given
     * inside the decrypted key (see the specification of the key format).
     *
     * @dev Emits a {DecryptionRequested} event.
     * @param id Consumer-defined context emitted with the request.
     * @param encryptedKey Encryption of a key.
     * @param callback The callback contract.
     * @param transaction General purpose transaction identifier.
     * @return requestId Oracle-assigned correlation identifier passed to the callback.
     */
    function requestDecrypt(
        uint256 id,
        bytes calldata encryptedKey,
        IKeyDecryptionOracleCallback callback,
        bytes calldata transaction
    ) external payable returns (uint256 requestId);

    /*------------------------------------------- FUNCTIONALITY: FULFILLMENT (should be guarded by onlyOracle) -------*/

    /**
     * @dev Fulfillment of a key generation request (issued by requestGenerateEncryptedHashedKeys).
     * Implementations MUST reject a receiver or transaction that differs from the request,
     * and MUST reject duplicate, missing, or unrequested keyIds. Array order has no semantic
     * meaning. A successful fulfillment MUST deliver the complete batch in one callback;
     * partial callbacks are forbidden. Best-effort + calldata fallback: see fulfillDecryption.
     *
     * @param requestId Correlation id from the request event.
     * @param keys Generated keys, identified by keyId.
     * @param receiverContract Contract that is eligible to receive the decryption.
     * @param transaction Transaction that is eligible to request decryption.
     */
    function fulfillEncryptedHashedKeysGeneration(
        uint256 requestId,
        IKeyDecryptionOracleCallback.EncryptedHashedKey[] calldata keys,
        address receiverContract,
        bytes calldata transaction
    ) external;

    /**
     * @dev Fulfillment of a batch verification request (issued by requestVerifyEncryptedKeys).
     * The result is all-or-nothing: partial success is forbidden. The proxy MUST require exactly
     * one result with the unchanged encryptedKey for every requested keyId, independent of array
     * order. If `verified` is true, every hashedKey MUST be non-empty and every key MUST resolve
     * to the same receiverContract and transaction. If false, receiverContract MUST be address(0),
     * transaction MUST be empty, and consumers MUST ignore hashedKey values. Best-effort + calldata
     * fallback: see fulfillDecryption.
     *
     * @param requestId Correlation id from the request event.
     * @param verified True only if the complete batch was verified.
     * @param keys Complete result set, identified by keyId and echoing every requested encryptedKey.
     * @param receiverContract Common contract eligible to receive decryption, or address(0) on rejection.
     * @param transaction Common transaction eligible to request decryption, or empty on rejection.
     */
    function fulfillEncryptedKeysVerification(
        uint256 requestId,
        bool verified,
        IKeyDecryptionOracleCallback.EncryptedHashedKey[] calldata keys,
        address receiverContract,
        bytes calldata transaction
    ) external;

    /**
     * @dev Fulfillment of a decryption request (issued by requestDecrypt).
     *
     * Best-effort + calldata fallback:
     * - Implementations MAY attempt to call the consumer callback and MAY NOT revert if the callback fails (incl. OOG).
     *   In such cases the implementation SHOULD signal failure via {CallbackFailed} and allow the off-chain oracle to retry.
     * - The fulfillment payload (e.g., `key`) is always present in the transaction calldata of this fulfill call.
     *   Off-chain systems can use the emitted log's `transactionHash` to fetch and decode tx input calldata using this ABI.
     * - Practical caveat: some RPC providers prune old transaction bodies; store decoded payload off-chain if needed.
     *
     * @param requestId Correlation id from the request event.
     * @param key Decrypted key if admissible, otherwise empty bytes.
     */
    function fulfillDecryption(uint256 requestId, bytes calldata key) external;
}

IKeyDecryptionOracleCallback - Interface of the Callback Contract receiving the results

You find the current version of IKeyDecryptionOracleCallback in src/main/solidity.

// SPDX-License-Identifier: CC0-1.0
pragma solidity >=0.8.0 <0.9.0;

/*------------------------------------------- DESCRIPTION ---------------------------------------------------------------------------------------*/

/**
 * @title ERC-7573 Decryption Oracle Callback Contract - the callback from an external decryption oracle.
 * @dev Interface specification for a smart contract that receives decryption/verification results
 *      (by bridging to an external oracle).
 *
 * Implementation guidance:
 * - Callback implementations SHOULD restrict who can call these methods (e.g. `require(msg.sender == oracleProxy)`).
 * - Callback implementations MUST validate a pending `(msg.sender, requestId)` of the expected operation kind
 *   and consume or mark it before applying callback effects.
 * - Callbacks SHOULD be cheap and should avoid reverting. If heavy work is required, store minimal state/events and
 *   perform the heavy logic in a separate pull/consume transaction initiated by the consumer.
 * - Callbacks MUST assume they may receive less than "all gas" (oracle may reserve headroom / cap forwarded gas).
 *
 * @author Christian Fries.
 * @notice See documentation for details.
 */
interface IKeyDecryptionOracleCallback {
    /**
     * @dev One generated or verified encrypted/hashed key and its semantic role.
     */
    struct EncryptedHashedKey {
        bytes32 keyId;
        bytes encryptedKey;
        bytes hashedKey;
    }

    /*------------------------------------------- EVENTS ---------------------------------------------------------------------------------------*/

    /**
     * @dev Emitted when a batch of encrypted/hashed keys has been obtained.
     * @param sender The sender (oracle/proxy).
     * @param requestId The oracle-assigned request identifier.
     * @param keys The generated keys, identified by keyId.
     * @param receiverContract The receiving contract.
     * @param transaction The transaction id.
     */
    event EncryptedHashedKeysGenerated(
        address sender,
        uint256 requestId,
        EncryptedHashedKey[] keys,
        address receiverContract,
        bytes transaction
    );

    /**
     * @dev Emitted when verification of an atomic encrypted-key batch has completed.
     * @param sender The sender (oracle/proxy).
     * @param requestId The oracle-assigned request identifier.
     * @param verified True only if the complete batch was verified.
     * @param keys The complete requested key set, identified by keyId. On rejection,
     *        hashedKey values MAY be empty but keyId and encryptedKey MUST still echo the request.
     * @param receiverContract The common receiving contract, or address(0) on rejection.
     * @param transaction The common transaction, or empty bytes on rejection.
     */
    event EncryptedKeysVerificationCompleted(
        address sender,
        uint256 requestId,
        bool verified,
        EncryptedHashedKey[] keys,
        address receiverContract,
        bytes transaction
    );

    /**
     * @dev Emitted when the decrypted key has been obtained.
     * @param sender The sender (oracle/proxy) that released the key.
     * @param requestId The oracle-assigned request identifier.
     * @param key The decrypted key.
     */
    event KeyReleased(address sender, uint256 requestId, bytes key);

    /**
     * @dev Emitted when the decryption of a key has been denied.
     * @param sender The sender (oracle/proxy).
     * @param requestId The oracle-assigned request identifier.
     */
    event DecryptionDenied(address sender, uint256 requestId);

    /*------------------------------------------- FUNCTIONALITY ---------------------------------------------------------------------------------------*/

    /**
     * @notice Called from the decryption oracle proxy contract.
     * @dev Implementations SHOULD validate the complete batch and emit
     * {EncryptedHashedKeysGenerated} (if eligible).
     * @param requestId The oracle-assigned request identifier.
     * @param keys The generated keys, identified by keyId.
     * @param receiverContract The receiving contract.
     * @param transaction The transaction id.
     */
    function onEncryptedHashedKeysGenerated(
        uint256 requestId,
        EncryptedHashedKey[] calldata keys,
        address receiverContract,
        bytes calldata transaction
    ) external;

    /**
     * @notice Called from the (possibly external) decryption oracle proxy after atomic
     * verification of an encrypted-key batch.
     * @dev Implementations MUST correlate the complete, role-tagged set to the pending
     * request and SHOULD emit {EncryptedKeysVerificationCompleted} (if eligible).
     * Implementations MUST use `verified`, rather than empty values, as the result status.
     * @param requestId The oracle-assigned request identifier.
     * @param verified True only if the complete batch was verified; partial success is forbidden.
     * @param keys The complete requested key set, identified by keyId. Array order has no meaning.
     * @param receiverContract The common receiving contract, or address(0) on rejection.
     * @param transaction The common transaction, or empty bytes on rejection.
     */
    function onEncryptedKeysVerificationCompleted(
        uint256 requestId,
        bool verified,
        EncryptedHashedKey[] calldata keys,
        address receiverContract,
        bytes calldata transaction
    ) external;

    /**
     * @notice Called from the (possibly external) decryption oracle proxy.
     * @dev Implementations SHOULD emit {KeyReleased} (if eligible).
     * @param requestId The oracle-assigned request identifier.
     * @param key Decrypted key.
     */
    function onKeyReleased(uint256 requestId, bytes calldata key) external;

    /**
     * @notice Called from the (possibly external) decryption oracle proxy.
     * This method will only be called if a decryption request was illegal and denied.
     *
     * @dev Implementations SHOULD emit {DecryptionDenied}.
     * @param requestId The oracle-assigned request identifier.
     */
    function onKeyDenied(uint256 requestId) external;
}

License

The code is distributed under the Apache License version 2.0, unless otherwise explicitly stated.