Repository navigation
fix(fees): align Studio with Consensus v0.6 economics - #1748
Conversation
Mirror cap-priced round quotes, configured ladder semantics, appeal profit reserves, exact 2.5x rewards, typed appeal funding, immutable top-up schedules, live appeal overlay pricing, latest appeal ABIs, decision guards, and surplus refunds. Expose the canonical quote over RPC so cross-stack tests no longer maintain a second Studio formula.
📝 WalkthroughWalkthroughThis change aligns Studio with updated protocol transaction flow. It adds fee-aware and lifecycle RPC handling, durable queue ordering, EVM envelope tracking, appeal decision metadata, salted GhostFactory address support, internal-message replay handling, new simulator fee helpers, and matching contract, worker, database, configuration, and UI updates. ChangesProtocol v0.6 lifecycle, ordering, and fee handling
Estimated code review effort: 5 (Critical) | ~120 minutes Merge Risk: 🟠 High · up to The PR changes public transaction admission and fee settlement, but the current implementation can accept an unverified sender identity, which may misattribute transactions and fees; related deployment and recovery paths also contain concrete failure cases. Merge should be blocked until the sender authorization and material runtime/deployment issues are addressed. Suggested reviewers: Sequence Diagram(s)sequenceDiagram
participant Client
participant RPC as protocol_rpc.endpoints
participant Parser as TransactionParser
participant TP as TransactionsProcessor
participant CS as ConsensusService
Client->>RPC: send_raw_transaction(raw tx)
RPC->>Parser: decode_signed_transaction(raw tx)
Parser-->>RPC: DecodedRollupTransaction
RPC->>TP: begin_evm_envelope(hash, sender, nonce)
alt lifecycle call
RPC->>TP: apply top-up / admit appeal / validate finalize
TP-->>RPC: target tx state updated
else protocol submission
RPC->>TP: lock queues and reserve storage
RPC->>TP: insert_transaction(..., commit=False)
RPC->>CS: add_transaction(..., calldata)
CS-->>RPC: tx id / emitted recipients
end
RPC->>TP: record_evm_envelope(result)
RPC-->>Client: envelope hash or tx id
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (3 warnings)
✅ Passed checks (2 passed)
Full details: Linked Issues checkExplanation The directly linked issue [ Full details: Out of Scope Changes checkExplanation The linked issue [ Full details: Docstring CoverageExplanation Docstring coverage is 40.12% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 324 functions across 50 files. (29 skipped: 19 unsupported, 10 over the file limit.) Full details: Description checkExplanation The description is comprehensive and covers the change scope, motivation, implementation decisions, testing, risks, dependencies, and release guidance. It does not use every template heading, and it omits the explicit issue reference and checklist, but it provides the required information in equivalent sections.
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
The branch's pin replaced a dead source ref; v0.123-dev has since moved to feat/leader-data-to-genvm:201dc510c together with its vendored leader public data codec (#1747), so the base side is the one the vendored code expects.
The pin inherited from v0.123-dev references the pre-merge feature branch feat/leader-data-to-genvm, whose branch was deleted after squash-merge; the commit is unreachable from any ref, so the source build's clone cannot read it (fatal: unable to read tree). The same work is v0.6-dev head 3c96be6de (feat(manager): carry opaque leader public data, #29), which also contains the previous pin d07f21da. v0.123-dev itself needs the same repin.
Treat GenVM v0.3 bucket 0 as the shared execution reservoir, bucket 1 as message fees, and buckets 2/3 as byte counters. Reconstruct the exact GenVM receipt meter to derive Consensus storage/event-write fees, and size recommendations for both chargeable execution and the enforced shared reservoir.
Cover the two topology boundaries behind validator appeals: a five-validator pool is exhausted by the initial committee, while twelve identities provide the full fresh seven-seat first jury and preserve the exact Consensus quote.
gltest owns separate fee argument adapters for deploys and writes. Bridge both so their public None defaults are treated as omitted by the fee-aware integration fixture, while explicit direct SDK fees=None stays gasless. Add a dependency-free regression covering both entry points.
Delivery context
Depends-On: genlayerlabs/genlayer-consensus#1526
Depends-On: genlayerlabs/genlayer-js#214
Depends-On: genlayerlabs/genlayer-py#110
Cross-stack qualification: genlayerlabs/genlayer-e2e#756; harness #748 is merged.
Node destination interface: genlayerlabs/genlayer-node#1800; E2E timeout qualification: genlayerlabs/genlayer-node#1818.
Independent economics oracle: genlayerlabs/genlayer-fee-distribution-simulator#30.
Consensus oracle enforcement: genlayerlabs/genlayer-consensus#1388.
Formal lifecycle and selection reference: genlayerlabs/od-consensus-tla#39.
Consensus is authoritative for deployed runtime behavior. The simulator independently checks economics; TLA+ and the written protocol specification supply lifecycle, input-domain, appeal-window, and appeal-selection invariants.
Problem and outcome
Studio had formula, lifecycle, authority, submission, and failure-recovery differences from the Consensus v0.6 train. This PR aligns implemented Studio behavior—not only displayed quotes—with current Consensus economics and closes applicable defects from the Consensus handoff campaign.
The result covers submission, activation, top-up, appeal, execution, settlement, cancellation, expiry, exact committee and rotation ladders, timeout and decision-bound lifecycle, message allocation and replay, contribution ownership and refunds, storage and receipt pricing, funding overlays, and failure recovery.
The leader-timeout appeal bond deliberately retains the configured source-round committee cost. For five validators it is
100 + 5 × 200 = 1,100; removing the timed-out leader changes replay membership, not the independent source-round cost used by the bond quote.Important implementation details
Undeterminedoutcome as Consensus.gen_getTransactionLifecycleandgen_estimateLatestAppealChargeRPCs.status: 0failure semantics and expose the local revert reason as additive receipt metadata. Envelope-only lifecycle calls are also returned byeth_getTransactionByHash, which lets standard viem receipt polling reach the durable receipt. The JS and Python train heads wait for these receipts, so rejected writes and top-ups cannot masquerade as successful submissions.gen_getTransactionStatussupports the Node v0.6 object request and response while preserving the legacy string response for existing Studio consumers.0xrecipient toaddress(0)before allocation matching, so discovered deploy budgets remain usable during reveal.useBalancechildren are excluded from the sender-funded allocation tree while remaining subject to the global cap.keccak256("")as the allocation wildcard while retainingbytes32(0)for deploys and unnamed calls.-32000 execution failedpath receives the intentional default-fee fallback.Consensus handoff audit
All 151 unique non-governance findings and controls in the consolidated Consensus handoff #1492 were inspected, including the cross-repository boundary controls from #1527 and #1528. Applicable fee, lifecycle, queue, appeal, message, and identity behavior is implemented and regression-covered. Solidity-only governance, staking, proxy-upgrade, EVM gas-bound pagination, and fixed-width arithmetic findings were classified as non-applicable to Studio rather than copied mechanically.
The Studio release-readiness audit additionally absorbed the applicable fixes from #1735, #1736, #1737, and #1746: zero-stake selection now raises the consensus-domain error, RNG construction is per call, native balance transfers use atomic SQL mutations, and method-call decoding handles complete RLP headers plus both leader-only values. Shared VRF constants and errors were separated to remove the circular import present in the source proposals. The valid error-disclosure half of #1739 is also included: unexpected exceptions are logged server-side and return only a stable generic JSON-RPC error. Wildcard CORS without credentials remains intentional for a public RPC used by arbitrary browser dapps; the proposed mandatory allowlist would break that supported surface.
The final audit added three forward-correctness fixes:
Those three Consensus PRs are expected-red handoffs and are not production fixes in #1526. Studio therefore implements the specified optimal behavior ahead of the currently deployed Solidity path for those cases; this is explicit forward correctness, not an accidental parity claim.
The release-review hardening pass also closes every verified behavioral finding: finalization repair obeys retry backoff; stale terminal leases cannot strand later work; zero-value appeal aborts persist rollback; nullable legacy nonces hash as zero; raw encoded allocation subtrees remain hashable but are not traversed; quote and admission share one appeal-eligibility computation; legacy envelope migration prefers dated rows; explicit integration
fees=Noneremains gasless; frontend and backend failed-appeal defaults agree; malformed Solidity tuple offsets return the protocol error; and default Docker builds honor the pinned GenVM source ref.Validation
Fresh appeal-capacity boundary regression: a five-validator pool is correctly exhausted by the initial committee; a 12-validator pool supplies the complete fresh seven-seat first jury and preserves the exact quote. Full
test_studio_fees.py: 467 passing; pre-commit passes.Backend unit suite: 1,553 passing; the 12 Unix-socket cases blocked by the desktop sandbox pass unchanged at host level. The explicit-
fees=Noneregression now imports only a dependency-free shared helper, matching the unit-only CI dependency boundary.The gltest compatibility bridge now treats gltest's default
(fees=None, fee_value=None)pair as omitted in both its deployment and write adapters, so fee-enabled integration submissions obtain the canonical Studio estimate while direct SDKfees=Noneremains explicitly gasless. Four dependency-free unit regressions cover omission semantics, forwarding, both transaction entry points, bridge installation, and idempotence.Validator session/snapshot regression slice: 31 passing, covering atomic replacement, request-scoped sessions, duplicate-event suppression, and partial non-empty cache repair. A local RPC smoke confirmed one replacement event and no redundant reload.
Isolated PostgreSQL suite: 235 passing and 1 expected xfail, including the real migration chain and a downgrade/upgrade duplicate-envelope backfill regression.
Atomic-transfer focused suite: 3 passing against the finalized source image.
Clean-process VRF import: passing without import-order preconditions.
Frontend unit suite: 218 passing across 33 files.
Hardhat suite: 22 passing, including malformed fee-aware offset rejection with the protocol custom error.
Frontend typecheck and production build: passing.
Immutable JS SDK pin resolves to 197 sim fe fix contract state and contract methods refresh after depl… #214
bc1fc320; its 184-test suite, type declarations, lint, build, and registry-drift check pass, and Studio'snpm ci --dry-runvalidates the exact repin. Python Remove unused env variables #11065865a55passes the 205 release-relevant unit tests, including schedule-free ordinary top-ups.Black check on all touched Python files: passing.
Prettier check on touched frontend files: passing.
ESLint on touched frontend files: no errors; 62 pre-existing warnings.
Repository pre-commit hooks and
git diff --check: passing.Fee/RPC regression slice, including internal deployment, salted address, envelope lookup, and shared-allocation accounting: 476 passing.
Shared-bucket regression covers an actual storage-writing estimate, proves the recommendation funds GenVM's enforced reservoir, and proves the Consensus payload receives only exact chargeable receipt plus storage/event-write consumption.
Shared E2E v0.5 and v0.6 typechecks against exact JS SDK 197 sim fe fix contract state and contract methods refresh after depl… #214: passing.
Shared E2E focused message-discovery scenario: all 23 steps resolve in dry-run.
054_fee_consensus_parity.featureruns the same canonical economics, appeal-funding, replay, and child-effect scenarios against Studio and dev-env/Consensus.051_fee_messages_internal.featuresubmits the exact fee envelope returned by Studio's allocation discovery and verifies real child execution and budget consumption.Exact review cut
6a353e425b69b30bca642e86c9bc4f0e6b1b10c7(synthetic mergecd3501ad10dfe3e94ab4a60f8d7f1a3f36281d4f)2f78febfc06866e59e7f12db848664e95ce99e8e(synthetic merge9d3406e606bf8228fb695a64dfadddc741e623b4)6666892c3ee124e3804e391688c4156a4736fdacbe00e5dc174f28899c7755ac32b0d155be6673e6(synthetic mergec94fe66f5ed2a923dea37e06fad557a7eec8378f)98d59cffce30895644c4901710494f8f375ad248(synthetic mergeef2015c1c633604328e1445c60398d55f081ff89)65865a55c58f9a9f199d5a178ee98db01b5e724a(synthetic mergeb3753b360ea46c219b0e77e6034655335dd3c4fd)eacb62a8788e578a1085c3286d95dd0a2a2e9c7df5e659b03e78527c0f06bcf28c9e26650aea11adb8f593b6b6530b5132aaa708ef1cfc559ee463567d6de26cf0218d599545afb3b01f0c88ee4cafe352398b17d51c8cf9a5da3313f19f6afa5afe1996703fc0338882df41184e7ec0e28f8590eb8c5382(synthetic merge410a9c7cfac913474715ed71868aeeb9a3926ac3)3c96be6defe30fd9843d47bedc0c66bec324d0fa4ddb57b68d2cb76eec01d94671e9594338f7e5a809fa7790f44a7d809eb9b429d8ca900e1b876c383e263455d8262ccb55d621920b1a96c96554123aRelease gate and risk
Studio currently pins immutable SDK commits so the prerelease can be qualified before coordinated package publication. Replace those pins with coordinated prerelease versions only when they contain these exact behaviors.
The default Studio Docker build now interprets the immutable
branch:commitbinding inthird_party/genvm/versionas source mode. Train images must prepare the sandboxed runner closure for exact source3c96be6defe30fd9843d47bedc0c66bec324d0fa, or explicitly select a separately qualified release withGENVM_TAG.Automatic allocation discovery is exact for root messages observed in the representative execution. Descendant allocations still require a manually supplied nested allocation tree when a caller needs to reserve those budgets explicitly; this is a documented capability boundary, not a formula mismatch.
Highest-risk surfaces are persisted fee accounting, asynchronous recovery, decision identity, and message replay. Rollback is the Studio commit stack on this PR; no external migration has been applied by publishing the branch.