Enclave is now The Interfold.
Build
The Interfold Contract

The Interfold Contract

This page describes the public API of the Interfold contract (Interfold.sol) for application builders. It covers the request function and its parameters, where inputs go, the two output functions, the read functions, the events, and the custom errors. At the end of the page, you can call the contract directly or read the calls that the SDK makes for you. For the stages and their deadlines in order, see E3 lifecycle.

What the contract does

The Interfold contract records each E3 and moves it through its stages. It does these tasks:

  • Accepts E3 requests and takes the fee.
  • Asks the CiphernodeRegistry to select a committee.
  • Records the committee public key commitment when the registry reports it.
  • Accepts the ciphertext output after the E3 program and the protocol verifier accept the proof.
  • Accepts the plaintext output after the decryption verifier accepts the proof.
  • Pays rewards on success and sends failed E3s to refund settlement.

The Interfold contract does not accept inputs. Each E3 program accepts its own inputs in its publishInput function. See Input publication.

  1. requestThe requester pays the fee. Interfold asks the registry for a committee.
  2. publishInputData providers send encrypted inputs to the E3 program, not to Interfold.
  3. publishCiphertextOutputA server sends a proof-backed reference to the encrypted result.
  4. publishPlaintextOutputCiphernodes send the decrypted result and the decryption proof.

Request an E3

The request function takes one struct and returns the new E3 ID and the stored E3 record.

function request(
  E3RequestParams calldata requestParams
) external returns (uint256 e3Id, E3 memory e3);

request pulls the fee with transferFrom. Before you call it, approve the Interfold contract to spend the quoted fee in the fee token. For the fee formula and the refund rules, see Request an E3.

Request parameters

E3RequestParams is defined in interfaces/IInterfold.sol.

FieldTypeMeaningRule
committeeSizeCommitteeSize (uint8)Minimum (0), Micro (1), or Small (2).The size must have thresholds configured. The pricing minimums must accept it.
inputWindowuint256[2]Start and end timestamps of the input window, in seconds.The start must not be in the past. The end must not be before the start.
e3ProgramIE3ProgramThe E3 program contract.The contract owner must register the program first.
paramSetuint8BFV parameter set. 0 is insecure-64, 2 is secure-8192.The chain must support the set, and the set must be registered.
computeProviderParamsbytesCompute provider settings.Interfold passes the bytes to e3Program.validate.
customParamsbytesApplication settings.Interfold stores the bytes on the E3 and passes them to e3Program.validate.
expectedFeeTokenIERC20The fee token that the requester accepts.Must equal feeToken(). Otherwise the call reverts with FeeTokenChanged.
expectedCryptoConfigIdbytes32The circuit configuration that the requester accepts.Must equal the ID for paramSet. Otherwise the call reverts with CryptoConfigChanged.
maxFeeuint256The largest total fee that the requester accepts.The quote must not be more than maxFee. Otherwise the call reverts.

The configuration IDs for each parameter set are constants in lib/ActiveCryptoConfig.sol (INSECURE_CONFIG_ID and SECURE_CONFIG_ID). The SDK fills expectedFeeToken, expectedCryptoConfigId, and maxFee for you. See SDK.

What request checks

request runs these checks in order. The first check that fails reverts the call.

  1. Requests are not paused (RequestsPaused). A new deployment starts with requests paused.
  2. The registry, bonding registry, slashing manager, refund manager, and node release registry form one consistent set (DependencyConfigurationMismatch).
  3. The current fee token is on the allow-list (FeeTokenNotAllowed).
  4. The E3 program is registered (E3ProgramNotAllowed).
  5. The quote succeeds. The quote checks the input window, the total duration, the parameter set, and the committee size.
  6. The current fee token, the configuration ID for paramSet, and the quote agree with expectedFeeToken, expectedCryptoConfigId, and maxFee.
  7. The E3 program validate call returns an encryption scheme ID. Interfold must have a decryption verifier and a public key verifier for that scheme (InvalidEncryptionScheme).
  8. The fee transfer delivers the exact amount (AssetTransferMismatch).
  9. The registry accepts the committee request. The registry reverts when fewer than N eligible ciphernodes (InsufficientCiphernodes) or fewer than N bond owners (InsufficientBondOwners) are available.

The total duration check uses the worst case. Interfold takes the later of the input window end and the committee setup time, then adds the compute window and the decryption window. The committee setup time is the randomness timeout, plus the sortition submission window, plus the DKG window. The total must not be more than maxDuration (InvalidDuration).

What request stores and emits

A successful request does these things:

  • Assigns the next E3 ID. The first ID is the Interfold address shifted left by 96 bits, so E3 IDs are large numbers.
  • Freezes the registry, bonding registry, refund manager, slashing manager, and timeout configuration for this E3.
  • Stores the service fee as escrow. It credits the flat randomness fee to the treasury.
  • Sets the stage to Requested.
  • Emits E3Requested(e3Id, e3, cryptoConfigId) and E3StageChanged(e3Id, None, Requested).

The E3 record

getE3(e3Id) returns the E3 struct from interfaces/IE3.sol.

FieldTypeContent
seeduint256Seed for the computation. Committee selection uses a separate VRF seed.
committeeSizeCommitteeSizeThe requested committee size.
requestBlockuint256The request timestamp. The name is kept for ABI compatibility.
inputWindowuint256[2]The requested input window.
encryptionSchemeIdbytes32The scheme that e3Program.validate returned.
e3ProgramIE3ProgramThe E3 program address.
paramSetuint8The BFV parameter set.
customParamsbytesThe application settings from the request.
decryptionVerifierIDecryptionVerifierThe verifier for the decryption proof.
pkVerifierIPkVerifierThe verifier for the DKG public key proof.
committeePublicKeybytes32The committee public key commitment. It is not the full key.
ciphertextOutputbytes32Keccak-256 of the serialized ciphertext output.
plaintextOutputbytesThe decrypted result.
requesteraddressThe account that called request.
ciphertextCommitmentbytes32The SAFE commitment to the ciphertext that the decryption proof uses.

Input publication

Inputs go to the E3 program. IE3Program defines the entry point:

function publishInput(uint256 e3Id, bytes memory data) external;

The E3 program decides the encoding of data, the checks, and the storage. Interfold does not check the input window for inputs. Interfold enforces the window only on the output: it rejects a ciphertext output before inputWindow[1]. The default template and CRISP use different input paths.

ProgramEncoding of dataWhere the ciphertext bytes go
MyProgram (templates/default)abi.encode(bytes ciphertext, bytes32 ciphertextCommitment)On-chain, in the InputPublished(e3Id, data, index) event. The contract inserts the commitment into a LazyIMT tree.
CRISPProgram (CRISP (opens in a new tab))A ballot proof, the voting slot, the ciphertext commitment and hash, the parent index, and a signed availability attestationTo Avail. publishInput reserves the tree leaf and emits InputCommitted. Later, finalizeInput checks the Avail receipt and emits InputPublished.

The template program does not prove that the ciphertext matches its commitment. A comment in MyProgram.sol states that a production program must verify this binding. For the program side, see Program contract.

Publish the ciphertext output

After the compute provider runs, a server publishes a reference to the encrypted result. The ciphertext bytes stay off Ethereum, on a data availability layer.

function publishCiphertextOutput(uint256 e3Id, bytes calldata encodedOutputReference) external;

encodedOutputReference is the ABI encoding of one CiphertextOutputReference tuple:

FieldTypeContent
contentHashbytes32Keccak-256 of the exact serialized ciphertext bytes.
ciphertextCommitmentbytes32The SAFE commitment to the decoded ciphertext.
computeProofbytesThe compute proof. It binds contentHash and the commitment.
availabilityProofbytesThe data availability receipt for contentHash.

Any account can call the function. The call succeeds only when all of these conditions are true:

  • The E3 is in KeyPublished.
  • The current time is at or after inputWindow[1] (InputDeadlineNotReached).
  • The current time is at or before the compute deadline (CommitteeDutiesCompleted).
  • No output exists yet (CiphertextOutputAlreadyPublished), and contentHash is not zero.
  • The committee still has enough active members (ThresholdNotMet from the registry).
  • e3Program.verifyDataAvailability(contentHash, availabilityProof) returns a receipt for the same contentHash.
  • The request-time protocol ciphertext verifier and e3Program.verify both accept the proof.

A receipt for a different hash, or a proof that a verifier rejects, reverts with InvalidOutput. The E3 program can also revert with its own error. On success, the E3 moves to CiphertextReady and the decryption deadline starts. The contract emits CiphertextOutputReferencePublished(e3Id, contentHash, ciphertextCommitment, availabilityBlock, availabilityLeafIndex) and E3StageChanged.

registerE3Program accepts only a program that implements IE3ProgramDataAvailability.verifyDataAvailability and advertises IE3Program and IE3ProgramDataAvailability through ERC-165. Otherwise it reverts with E3ProgramInterfaceMissing. The template version checks only that the proof bytes hash to contentHash. It is for local development.

Publish the plaintext output

The committee decrypts the output, and one ciphernode publishes the result and the proof.

function publishPlaintextOutput(
  uint256 e3Id,
  bytes calldata plaintextOutput,
  bytes calldata proof
) external returns (bool success);

The call succeeds only when the E3 is in CiphertextReady and the decryption deadline has not passed. The proof must not be empty (ProofRequired). The committee must still be viable, and the decryption verifier must accept the proof.

On success, the E3 moves to Complete. The contract credits the treasury share and the committee rewards. It emits RewardsDistributed, PlaintextOutputPublished(e3Id, plaintextOutput, proof), and E3StageChanged. Rewards are pull payments. Each recipient calls claimReward(e3Id) or claimRewards(e3Ids).

Failure functions

These functions handle an E3 that does not finish. For the rules and the refund amounts, see Request an E3.

FunctionCallerEffect
checkFailureCondition(e3Id)Anyone (view)Returns (canFail, reason) for the current stage deadline.
markE3Failed(e3Id)Anyone after the grace periodMoves an overdue E3 to Failed with a timeout reason.
cancelE3(e3Id)The requester onlyFails an E3 whose randomness request expired without a usable result.
processE3Failure(e3Id)AnyoneSends the service escrow to the refund manager and calculates the refund.

During markFailedGracePeriod after a deadline, only the requester, the contract owner, or an active committee member can call markE3Failed (MarkE3FailedInGracePeriod).

Read functions

These view functions are the ones that applications use most.

FunctionReturns
getE3(e3Id)The E3 record. Reverts with E3DoesNotExist for an unknown ID.
getE3Stage(e3Id)The E3Stage value.
getFailureReason(e3Id)The FailureReason value. None when the E3 has not failed.
getRequester(e3Id)The requester address.
getDeadlines(e3Id)E3Deadlines { dkgDeadline, computeDeadline, decryptionDeadline }.
getE3TimeoutConfig(e3Id)The timeout windows frozen at request time.
getE3LifecycleDeadline(e3Id)The latest possible lifecycle deadline, set at request time.
getTimeoutConfig()The current E3TimeoutConfig { dkgWindow, computeWindow, decryptionWindow }.
getE3Quote(params)The total fee for an E3RequestParams value at the current block.
getPricingConfig()The current PricingConfig.
feeToken(), feeTokenDecimals()The current fee token and its expected decimals.
isFeeTokenAllowed(token)Whether a token is on the fee-token allow-list.
requestsPaused()Whether new requests revert.
e3Programs(program)Whether a program is registered for new requests.
paramSetRegistry(paramSet)The ABI-encoded BFV parameters. Empty when the set is not registered.
committeeThresholds(size, index)Index 0 is H and index 1 is N for a committee size.
e3CryptoConfigIds(e3Id)The configuration ID frozen for an E3.
maxDuration(), markFailedGracePeriod()The duration limit and the failure grace period, in seconds.
pendingReward(e3Id, account)The reward that an account can claim for an E3.
ciphernodeRegistry(), e3RefundManager()The current registry and refund manager.

Events

The Interfold contract emits these events for the E3 lifecycle.

EventEmitted when
E3Requestedrequest succeeds. It carries the full E3 record and the indexed configuration ID.
E3StageChangedAny stage changes. It carries the previous stage and the new stage.
CommitteeFinalizedThe registry finalizes the committee.
CommitteeFormedThe registry reports the committee public key, and the E3 moves to KeyPublished.
CiphertextOutputReferencePublishedpublishCiphertextOutput succeeds.
PlaintextOutputPublishedpublishPlaintextOutput succeeds.
RewardsDistributed, RewardCreditedRewards are credited after success.
TreasuryCreditedThe randomness fee is credited at request time, or the protocol share is credited at success.
E3FailedAn E3 fails. It carries the stage at failure and the FailureReason.
E3FailureReclassifiedAn expulsion changes a requester-paid failure reason to a ciphernode-paid reason.
E3FailureProcessedprocessE3Failure sends the escrow to the refund manager.

IInterfold also declares InputPublished and CiphertextOutputPublished. The Interfold contract does not emit them. E3 programs emit their own input events, and new outputs use CiphertextOutputReferencePublished.

The CiphernodeRegistry emits the committee events. Applications use these most:

Registry eventContent
CommitteeRandomnessRequestedThe randomness request ID, the provider, and the randomness deadline.
SortitionCommitteeFinalizedThe selected committee and the ticket scores.
CommitteeFormationFailedToo few tickets or no usable randomness at finalization.
CommitteeProofPublishedThe committee, the public key commitment, and the verified DKG proof.
CommitteePublicKeyChunkPublishedOne chunk of the serialized public key. Clients join the chunks to get the full key.

Custom errors

These errors are the ones that an application sees most. All are declared in IInterfold, except the registry errors.

ErrorCause
RequestsPaused()The owner paused new requests.
FeeTokenNotAllowed(token)The current fee token is not on the allow-list.
E3ProgramNotAllowed(program)The program is not registered.
InvalidInputDeadlineStart(start), InvalidInputDeadlineEnd(end)The input window starts in the past or ends before it starts.
InvalidDuration(duration)The worst-case lifecycle is longer than maxDuration.
UnsupportedCryptoConfig()The chain does not support the parameter set or the committee shape.
CommitteeSizeNotConfigured(size)No thresholds are set for the committee size.
CommitteeSizeTooSmall(size), ThresholdTooSmall(threshold)The committee size is below the pricing minimums.
FeeTokenChanged(expected, actual)expectedFeeToken is not the current fee token.
CryptoConfigChanged(expected, actual)expectedCryptoConfigId is not the ID for paramSet.
FeeExceedsMaximum(fee, maximum)The quote is more than maxFee.
InvalidEncryptionScheme(id)No verifier is set for the scheme that the program returned.
InsufficientCiphernodes(requested, available)Registry: too few eligible ciphernodes for N.
InputWindowClosedBeforeKeyPublication(e3Id, inputDeadline)The committee tried to publish its key after the input window closed.
InvalidStage(e3Id, expected, actual)The call is not valid in the current stage.
InputDeadlineNotReached(e3Id, inputDeadline)A ciphertext output arrived before the input window closed.
CommitteeDutiesCompleted(e3Id, expiration)An output arrived after its deadline.
CiphertextOutputAlreadyPublished(e3Id)The E3 already has a ciphertext output.
InvalidOutput(output)The data availability receipt or the compute proof failed.
ProofRequired()The plaintext proof is empty.
FailureConditionNotMet(e3Id)markE3Failed was called before the stage deadline passed.
E3NotCancellable(e3Id, stage)cancelE3 was called outside its narrow condition.

Security considerations

  • Committee size. The committee enum fixes N, H, and T. You cannot choose other thresholds. A larger committee costs more because the quote grows with N and H.
  • Input validation. Interfold does not see inputs. Your E3 program must check who can submit, when, and what. It must also bind each ciphertext to its commitment.
  • Output verification. Interfold accepts a ciphertext output only if your program's verify accepts the proof. A weak verify gives a weak guarantee. Your E3s also depend on the trust model of your compute provider.
  • Event finality. A reorganization can remove an event that you already read. Wait for enough confirmations before you act on an event that moves funds or ends a process.

Next steps