Skip to content

feat: implement parametric E3 pricing [skip-line-limit]#1422

Open
hmzakhalid wants to merge 17 commits intomainfrom
feat/e3-pricing
Open

feat: implement parametric E3 pricing [skip-line-limit]#1422
hmzakhalid wants to merge 17 commits intomainfrom
feat/e3-pricing

Conversation

@hmzakhalid
Copy link
Member

@hmzakhalid hmzakhalid commented Mar 13, 2026

E3 fees should be a function of committee size ($c^1$), decryption threshold ($c^2$), time availability ($\hat{t}$), and publication costs. The critical insight is that coordination costs in a flat committee topology scale quadratically with $O\binom{n}{2}$ pairwise interactions, so the fee formula must capture this or large committees become economically unsustainable for ciphernodes.

How the pricing works

The fee formula in getE3Quote():

baseFee = keyGenPerNode × n                           // Linear: key generation
        + coordinationPerPair × n(n-1)/2              // Quadratic: DKG coordination
        + availabilityPerNodePerSec × n × duration    // Linear × time: availability
        + decryptionPerNode × m                       // Linear: decryption
        + coordinationPerPair × m(m-1)/2              // Quadratic: decryption coordination
        + publicationBase                             // Fixed: on-chain publication

fee = baseFee × (10000 + marginBps) / 10000           // Apply governance markup

Where:

  • n = total committee size (threshold[1])
  • m = quorum/decryption threshold (threshold[0])
  • duration = inputWindow[1] - inputWindow[0] + dkgWindow + computeWindow + decryptionWindow
  • marginBps = governance-tunable markup (default 10%)

On successful completion, _distributeRewards() now splits the fee:

  • protocolShareBps (e.g. 20%) → protocol treasury
  • Remainder -> equally among active (non-expelled) committee members via BondingRegistry

Summary by CodeRabbit

  • New Features

    • Configurable pricing (get/set) with pricing update event and on-chain initialization; dynamic E3 quote now reflects committee size, duration, and margins.
  • Bug Fixes

    • Reward distribution updated to split protocol treasury fees from committee payouts and handle dust/bonding correctly.
  • Tests

    • Added end-to-end pricing and governance tests validating quotes, fee splits, access controls, and input validations.
  • Chores

    • Updated deployment flow to set pricing, example configs, environment sample, and CI/artifact metadata.

@vercel
Copy link

vercel bot commented Mar 13, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
crisp Ready Ready Preview, Comment Mar 25, 2026 7:13pm
enclave-docs Ready Ready Preview, Comment Mar 25, 2026 7:13pm

Request Review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 13, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds an on-chain PricingConfig to Enclave, dynamic fee computation in getE3Quote, owner-settable pricing via setPricingConfig, protocol treasury share extraction in reward distribution, committee threshold validations, tests, and deployment/script/config updates.

Changes

Cohort / File(s) Summary
Core Pricing & Interface
packages/enclave-contracts/contracts/interfaces/IEnclave.sol, packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json
Added PricingConfig struct, PricingConfigUpdated event, setPricingConfig(PricingConfig) and getPricingConfig() signatures; artifact ABI updated.
Enclave Implementation
packages/enclave-contracts/contracts/Enclave.sol
Stored global _pricingConfig and per-request protocol snapshot; replaced fixed getE3Quote logic with view computation using pricing and committee parameters; owner-only setter with validations; reward distribution now splits protocol treasury share before node payouts; initialization updated.
Tests
packages/enclave-contracts/test/Pricing/Pricing.spec.ts
New comprehensive tests for getE3Quote formula, setPricingConfig governance/validation/event, protocol treasury splitting behavior, committee threshold minimum enforcement, and end-to-end request/fee charging flows.
Deployment & Scripts
packages/enclave-contracts/scripts/deployEnclave.ts, packages/enclave-contracts/scripts/deployAndSave/mockPkVerifier.ts, packages/enclave-contracts/scripts/deployMocks.ts
deployEnclave now calls setPricingConfig(...) with initial params and logs the tx; minor formatting simplifications in mock deploy scripts.
Artifacts / Metadata
packages/enclave-contracts/artifacts/.../IBondingRegistry.json, .../ICiphernodeRegistry.json, .../ISlashingManager.json, .../CiphernodeRegistryOwnable.json
Updated buildInfoId metadata entries only; no ABI or functional changes.
CRISP Example & Env
examples/CRISP/enclave.config.yaml, examples/CRISP/packages/crisp-contracts/deployed_contracts.json, examples/CRISP/server/.env.example
Normalized YAML quoting/formatting, updated deployed contract addresses and block numbers for the example, and updated E3_PROGRAM_ADDRESS in the example env.
CI Workflow
.github/workflows/ci.yml
Fixed malformed runs-on formatting and removed trailing whitespace in a job condition.

Sequence Diagram

sequenceDiagram
    participant Client as Client
    participant Enclave as Enclave (contract)
    participant Pricing as PricingConfig (storage)
    participant Treasury as ProtocolTreasury
    participant Nodes as CommitteeNodes

    Client->>Enclave: call getE3Quote(params)
    Enclave->>Pricing: read PricingConfig
    Pricing-->>Enclave: pricing fields
    Enclave->>Enclave: compute fee (components + duration + margin)
    Enclave-->>Client: fee (view)

    Client->>Enclave: request(...) with USDC approval & transfer
    Enclave->>Enclave: _distributeRewards(totalFee, committee)
    Enclave->>Treasury: transfer protocolShare (protocolShareBps)
    Enclave->>Nodes: distribute remainder among committee nodes
    Nodes-->>Enclave: ack
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • ctrlc03
  • cedoor

Poem

🐰
A config snapped into the chain, so neat,
Fees now dance with margins and a treasury seat.
Nodes share wisely, protocol gets its part,
Owner sets the rules, the quote's a work of art.
This rabbit hops — the contracts sing, on beat!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely describes the main feature addition: implementing a parametric pricing mechanism for E3 fees, which is reflected throughout the changeset (new PricingConfig struct, setPricingConfig/getPricingConfig functions, parametric getE3Quote logic, and reward distribution updates).

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/e3-pricing

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/enclave-contracts/contracts/interfaces/IEnclave.sol`:
- Around line 79-92: The PricingConfig struct includes publicationPerByte but
getE3Quote never uses it; update the fee logic in getE3Quote to include a
per-byte publication charge by adding (pricing.publicationPerByte * outputSize)
to the publication fee (ensure getE3Quote has or accepts an outputSize/numBytes
parameter and use pricing.publicationBase + pricing.publicationPerByte *
outputSize), or if per-byte pricing is not intended, remove publicationPerByte
from PricingConfig and all initializations and deployments that set it;
reference the PricingConfig struct, its publicationPerByte field, and the
getE3Quote function when making the change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c0133057-ac67-4583-99ae-52a9d243fbe6

📥 Commits

Reviewing files that changed from the base of the PR and between 6bcf88c and 7cbbf0d.

📒 Files selected for processing (8)
  • packages/enclave-contracts/artifacts/contracts/interfaces/IBondingRegistry.sol/IBondingRegistry.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/ISlashingManager.sol/ISlashingManager.json
  • packages/enclave-contracts/contracts/Enclave.sol
  • packages/enclave-contracts/contracts/interfaces/IEnclave.sol
  • packages/enclave-contracts/scripts/deployEnclave.ts
  • packages/enclave-contracts/test/Pricing/Pricing.spec.ts

@vercel vercel bot temporarily deployed to Preview – crisp March 13, 2026 18:44 Inactive
@vercel vercel bot temporarily deployed to Preview – enclave-docs March 13, 2026 18:44 Inactive
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
packages/enclave-contracts/contracts/Enclave.sol (1)

569-583: Skip CN reward transfer path when CN allocation is zero.

Avoid external approve/distribute calls when cnAmount == 0; it reduces unnecessary risk and call overhead.

♻️ Suggested change
-        paymentToken.forceApprove(address(bondingRegistry), cnAmount);
-
-        bondingRegistry.distributeRewards(paymentToken, activeNodes, amounts);
-
-        paymentToken.forceApprove(address(bondingRegistry), 0);
+        if (cnAmount > 0) {
+            paymentToken.forceApprove(address(bondingRegistry), cnAmount);
+            bondingRegistry.distributeRewards(paymentToken, activeNodes, amounts);
+            paymentToken.forceApprove(address(bondingRegistry), 0);
+        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/enclave-contracts/contracts/Enclave.sol` around lines 569 - 583, The
CN reward path should be skipped when cnAmount == 0 to avoid unnecessary
approves/calls; in the function handling distribution, add a guard that if
cnAmount == 0 you do not build the amounts array, call
paymentToken.forceApprove(address(bondingRegistry), ...), or call
bondingRegistry.distributeRewards(paymentToken, activeNodes, amounts). Locate
the block that computes amount/amounts/distributed and the subsequent calls to
paymentToken.forceApprove and bondingRegistry.distributeRewards and wrap them in
a conditional (or early continue/return) so they run only when cnAmount > 0.
packages/enclave-contracts/test/Pricing/Pricing.spec.ts (1)

331-342: Unused helper function.

The makeRequest helper is defined but not used in any of the test cases. Tests at lines 597-598, 679-680, and 766-767 manually call approve and request instead.

Consider either using this helper in the tests for consistency or removing it to reduce dead code.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/enclave-contracts/test/Pricing/Pricing.spec.ts` around lines 331 -
342, The helper makeRequest is unused; either remove it or refactor tests to use
it for consistency: replace the manual sequences of calling enclave.getE3Quote/
usdcToken.approve(...) and enclave.request(...) in the tests that manually
perform approve+request with a single call to makeRequest(enclave, usdcToken,
requestParams, signer) (ensure signer is passed when tests connect contracts) so
fee retrieval and approval are centralized via makeRequest; alternatively,
delete the makeRequest function if you prefer to keep the explicit
approve/request flows (remove references to makeRequest and its imports like
Enclave.getE3Quote and MockUSDC if orphaned).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/enclave-contracts/contracts/Enclave.sol`:
- Around line 1043-1053: The setPricingConfig function currently allows a
PricingConfig with protocolShareBps > 0 and protocolTreasury == address(0),
which causes protocol rewards to be skipped; update the validation in
setPricingConfig to reject such configs by adding a require that when
config.protocolShareBps > 0 then config.protocolTreasury != address(0) before
assigning _pricingConfig and emitting PricingConfigUpdated; reference the
PricingConfig struct fields protocolShareBps and protocolTreasury and the
setPricingConfig function/_pricingConfig assignment to locate where to add this
check.
- Around line 1071-1075: The getE3Quote function currently doesn't validate that
the provided committee size is configured in committeeThresholds; add the same
guard used in request() by loading uint32[2] memory threshold =
committeeThresholds[committeeSize] (or using requestParams.committeeSize if that
variable is in scope) and require that threshold[1] != 0 (or both elements
non-zero) with a clear revert string like "invalid committee size" before using
threshold to compute n and m; this mirrors request() behavior and prevents
unconfigured sizes from being accepted.

---

Nitpick comments:
In `@packages/enclave-contracts/contracts/Enclave.sol`:
- Around line 569-583: The CN reward path should be skipped when cnAmount == 0
to avoid unnecessary approves/calls; in the function handling distribution, add
a guard that if cnAmount == 0 you do not build the amounts array, call
paymentToken.forceApprove(address(bondingRegistry), ...), or call
bondingRegistry.distributeRewards(paymentToken, activeNodes, amounts). Locate
the block that computes amount/amounts/distributed and the subsequent calls to
paymentToken.forceApprove and bondingRegistry.distributeRewards and wrap them in
a conditional (or early continue/return) so they run only when cnAmount > 0.

In `@packages/enclave-contracts/test/Pricing/Pricing.spec.ts`:
- Around line 331-342: The helper makeRequest is unused; either remove it or
refactor tests to use it for consistency: replace the manual sequences of
calling enclave.getE3Quote/ usdcToken.approve(...) and enclave.request(...) in
the tests that manually perform approve+request with a single call to
makeRequest(enclave, usdcToken, requestParams, signer) (ensure signer is passed
when tests connect contracts) so fee retrieval and approval are centralized via
makeRequest; alternatively, delete the makeRequest function if you prefer to
keep the explicit approve/request flows (remove references to makeRequest and
its imports like Enclave.getE3Quote and MockUSDC if orphaned).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dbaabff4-e0dd-4bf1-98d5-5cafe3138c02

📥 Commits

Reviewing files that changed from the base of the PR and between 7cbbf0d and a063b77.

📒 Files selected for processing (11)
  • packages/enclave-contracts/artifacts/contracts/interfaces/IBondingRegistry.sol/IBondingRegistry.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/ISlashingManager.sol/ISlashingManager.json
  • packages/enclave-contracts/artifacts/contracts/token/EnclaveTicketToken.sol/EnclaveTicketToken.json
  • packages/enclave-contracts/artifacts/contracts/verifier/DkgPkVerifier.sol/DkgPkVerifier.json
  • packages/enclave-contracts/artifacts/contracts/verifier/DkgPkVerifier.sol/ZKTranscriptLib.json
  • packages/enclave-contracts/contracts/Enclave.sol
  • packages/enclave-contracts/contracts/interfaces/IEnclave.sol
  • packages/enclave-contracts/scripts/deployEnclave.ts
  • packages/enclave-contracts/test/Pricing/Pricing.spec.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/enclave-contracts/artifacts/contracts/verifier/DkgPkVerifier.sol/ZKTranscriptLib.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • packages/enclave-contracts/artifacts/contracts/interfaces/ISlashingManager.sol/ISlashingManager.json
  • packages/enclave-contracts/contracts/interfaces/IEnclave.sol
  • packages/enclave-contracts/scripts/deployEnclave.ts

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@packages/enclave-contracts/artifacts/contracts/verifier/ThresholdPkAggregationVerifier.sol/ZKTranscriptLib.json`:
- Around line 393-394: Update the artifact metadata so inputSourceName matches
the actual source: replace the incorrect "inputSourceName":
"project/contracts/verifier/DkgPkVerifier.sol" with
"project/contracts/verifier/ThresholdPkAggregationVerifier.sol" in the
ZKTranscriptLib.json artifact (the one containing the ZKTranscriptLib entry) so
it aligns with the existing sourceName and other artifacts; ensure the change is
applied to the artifact JSON that references ThresholdPkAggregationVerifier.sol
to keep build metadata consistent.

In `@packages/enclave-contracts/contracts/Enclave.sol`:
- Around line 1066-1077: After loading threshold and deriving n and m in
getE3Quote/request paths, add runtime checks that enforce the stored values meet
current pricing-config minimums: require(n >= pc.minCommitteeSize && m >=
pc.minThreshold) (with appropriate error/revert like
CommitteeSizeTooSmall/ThresholdTooSmall) so previously-written thresholds cannot
bypass governance-updated minimums; locate the check right after "uint256 n =
uint256(threshold[1]); uint256 m = uint256(threshold[0]); PricingConfig memory
pc = _pricingConfig;" in the getE3Quote and request-related code paths and use
the existing PricingConfig fields (minCommitteeSize/minThreshold) and existing
error types or add clear revert errors if needed.
- Around line 1079-1083: The subtraction of requestParams.inputWindow[0] from
requestParams.inputWindow[1] can underflow; before computing duration, add an
explicit guard like require(requestParams.inputWindow[1] >=
requestParams.inputWindow[0], "InvalidInputWindow") (or revert with your
domain-specific error) to validate ordering of requestParams.inputWindow, then
compute duration using the existing expression that adds
_timeoutConfig.dkgWindow, _timeoutConfig.computeWindow and
_timeoutConfig.decryptionWindow; ensure the check is placed immediately before
the duration calculation that references requestParams.inputWindow and
_timeoutConfig.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 85cb6d50-c087-46f2-bd3d-81a4a9acf2de

📥 Commits

Reviewing files that changed from the base of the PR and between a063b77 and 1a5d434.

📒 Files selected for processing (3)
  • packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json
  • packages/enclave-contracts/artifacts/contracts/verifier/ThresholdPkAggregationVerifier.sol/ZKTranscriptLib.json
  • packages/enclave-contracts/contracts/Enclave.sol
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json

@hmzakhalid hmzakhalid marked this pull request as draft March 16, 2026 18:00
@hmzakhalid hmzakhalid linked an issue Mar 21, 2026 that may be closed by this pull request
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/enclave-contracts/contracts/Enclave.sol`:
- Around line 565-579: The protocol split is using live _pricingConfig values
during payout, allowing owner changes between request() and
publishPlaintextOutput() to redirect fees; mirror the existing _e3FeeTokens
snapshot approach by adding snapshot fields (e.g., protocolShareBps and
protocolTreasury) to the Request struct when request() is created and set them
from _pricingConfig at that time, then change the payout logic that currently
reads _pricingConfig.protocolShareBps and _pricingConfig.protocolTreasury to use
the stored request.protocolShareBps and request.protocolTreasury (and keep the
existing protocolAmount calculation and transfer steps). Ensure any related
codepaths that assume _pricingConfig are updated to use the request-level
snapshot to preserve token-rotation safety.
- Around line 1137-1151: The code currently hard-codes proofsPerNode = 6 + 2 *
(n - 1) * 2 which embeds a "2-moduli" BFV assumption; update the calculation to
derive the moduli count from validated params instead of the magic 2 (or remove
proof-count surcharges from the quote path). Specifically, replace the literal 2
with a parameter (e.g., use pc.dkgModuliCount or compute dkgModuliCount from the
E3 params) when computing proofsPerNode, or move proofsPerNode-related
surcharges out of the quote calculation that uses keyGenFixedPerNode,
keyGenPerEncryptionProof, coordinationPerPair and verificationPerProof so the
quote uses only the validated n/m/duration/publication inputs; ensure
proofsPerNode is computed from the actual DKG modulus count and any L_dkg factor
available in the parameter set and validate that parameter before using it.

In `@packages/enclave-contracts/scripts/deployEnclave.ts`:
- Around line 236-252: The pricing config currently hardcodes protocolTreasury
to ownerAddress in the call to enclave.setPricingConfig, which routes fees to
the deployer; change this to accept a configurable treasury parameter (e.g.,
pass a treasuryAddress variable or CLI/env value) and use that when calling
setPricingConfig instead of ownerAddress; update any function signatures or
deployment argument parsing that constructs the config so the treasury can be
supplied (reference enclave.setPricingConfig, protocolTreasury, and
ownerAddress) and ensure a sensible default or validation if the treasury is
missing.

In `@packages/enclave-contracts/test/Pricing/Pricing.spec.ts`:
- Around line 524-529: The assertions compare bigint-returned uint256 fields to
JS numbers (e.g., expect(pc.marginBps).to.equal(0)), which fails under ethers
v6; update tests to use bigint literals for expected values (e.g., 0n, 50000n)
wherever getPricingConfig() or other contract calls return bigint
fields—specifically change assertions in the "allows setting margin to 0" test
that reference getPricingConfig()/pc.marginBps and update all assertions in the
"Default pricing parameters" test to use bigint literals matching the contract
defaults.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3209954e-1fce-43b7-a260-1caaf51b8012

📥 Commits

Reviewing files that changed from the base of the PR and between 1a5d434 and f5f3094.

📒 Files selected for processing (15)
  • examples/CRISP/enclave.config.yaml
  • examples/CRISP/packages/crisp-contracts/deployed_contracts.json
  • examples/CRISP/server/.env.example
  • packages/enclave-contracts/artifacts/contracts/Enclave.sol/Enclave.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/IBondingRegistry.sol/IBondingRegistry.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/ISlashingManager.sol/ISlashingManager.json
  • packages/enclave-contracts/artifacts/contracts/registry/CiphernodeRegistryOwnable.sol/CiphernodeRegistryOwnable.json
  • packages/enclave-contracts/contracts/Enclave.sol
  • packages/enclave-contracts/contracts/interfaces/IEnclave.sol
  • packages/enclave-contracts/scripts/deployAndSave/mockPkVerifier.ts
  • packages/enclave-contracts/scripts/deployEnclave.ts
  • packages/enclave-contracts/scripts/deployMocks.ts
  • packages/enclave-contracts/test/Pricing/Pricing.spec.ts
✅ Files skipped from review due to trivial changes (6)
  • packages/enclave-contracts/scripts/deployAndSave/mockPkVerifier.ts
  • packages/enclave-contracts/scripts/deployMocks.ts
  • packages/enclave-contracts/artifacts/contracts/interfaces/IBondingRegistry.sol/IBondingRegistry.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/ICiphernodeRegistry.sol/ICiphernodeRegistry.json
  • packages/enclave-contracts/artifacts/contracts/registry/CiphernodeRegistryOwnable.sol/CiphernodeRegistryOwnable.json
  • packages/enclave-contracts/artifacts/contracts/interfaces/ISlashingManager.sol/ISlashingManager.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/enclave-contracts/artifacts/contracts/interfaces/IEnclave.sol/IEnclave.json

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
packages/enclave-contracts/contracts/Enclave.sol (1)

1145-1159: ⚠️ Potential issue | 🟠 Major

The quote formula still charges non-spec proof surcharges.

The PR objective defines getE3Quote() in terms of n, m, duration, coordination, availability, decryption, publication, and margin. Lines 1145-1159 add proof-count and verification costs with a hard-coded 2-moduli assumption, so on-chain fees will not match the published pricing formula.

🧮 Minimal fix to align the quote path with the stated formula
-        // ZK proof count per node: 6 fixed + 2 × (N-1) × L_dkg scaling
-        // TODO: get dkgModuliCount from E3 params instead of hardcoding
-        uint256 proofsPerNode = 6 + 2 * (n - 1) * 2;
-
-        // Key generation cost: fixed per-node + per-proof (quadratic in n)
+        // Key generation cost (linear in n)
         uint256 baseFee = pc.keyGenFixedPerNode * n;
-        baseFee += pc.keyGenPerEncryptionProof * n * proofsPerNode;
 
         // Key generation coordination cost (quadratic in n)
         if (n > 1) {
             baseFee += (pc.coordinationPerPair * (n * (n - 1))) / 2;
         }
 
-        // Proof verification cost: each node verifies all others' proofs (quadratic)
-        baseFee += pc.verificationPerProof * n * proofsPerNode;
-
         // Availability cost (linear in n × duration)
         baseFee += pc.availabilityPerNodePerSec * n * duration;
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/enclave-contracts/contracts/Enclave.sol`:
- Around line 573-586: The protocol treasury split is being skipped on the early
return when activeLength == 0; compute and apply the protocol share using
_e3ProtocolShareBps[e3Id] and _e3ProtocolTreasury[e3Id] (calculate
protocolAmount and call paymentToken.safeTransfer to _protocolTreasury if >0)
before the zero-active-member refund path/return so the treasury still receives
its configured share even when all committee members are expelled; ensure you
still subtract protocolAmount from the remaining refund logic (cnAmount =
totalAmount - protocolAmount).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 79faf048-d2c4-44fd-a3b3-f404257fa76c

📥 Commits

Reviewing files that changed from the base of the PR and between f5f3094 and 5f2f2a0.

📒 Files selected for processing (3)
  • .github/workflows/ci.yml
  • packages/enclave-contracts/contracts/Enclave.sol
  • packages/enclave-contracts/scripts/deployEnclave.ts


/// @inheritdoc IEnclave
function setPricingConfig(PricingConfig calldata config) public onlyOwner {
require(config.marginBps <= BPS_BASE, "Margin exceeds 100%");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we use custom errors to be consistent?


uint256 cnAmount = totalAmount - protocolAmount;

if (activeLength == 0) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we do this before we pay the protocol? as in, should requesters be made whole if all nodes were malicious?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

E3 Pricing Design getE3Quote

2 participants