Skip to content

QuantaPool v2: fixed-balance model, security fixes, Hyperion port#12

Merged
moscowchill merged 20 commits intomainfrom
dev
Mar 12, 2026
Merged

QuantaPool v2: fixed-balance model, security fixes, Hyperion port#12
moscowchill merged 20 commits intomainfrom
dev

Conversation

@moscowchill
Copy link
Copy Markdown
Contributor

Summary

  • Rebasing → fixed-balance model: stQRL now uses stable share balances (balanceOf()) with a separate getQRLValue() for QRL equivalent, matching wstETH design (tax-friendly)
  • Security remediations: Virtual shares (1e3) prevent first-depositor inflation attacks, locked withdrawal shares prevent transfer during queue, owner-adjustable minDeposit floor
  • ValidatorManager contract: Tracks validator lifecycle (Pending → Active → Exiting → Exited / Slashed) with Dilithium pubkey storage and batch activation
  • VALIDATOR_STAKE corrected to 40,000 QRL per Zond mainnet config
  • Hyperion port layer: sync-hyperion.js generates .hyp mirrors from Solidity sources, with dedicated compile and deploy scripts for Zond
  • Directory reorganization: Contracts moved to contracts/solidity/, v1 contracts to v1-deprecated/, docs reorganized
  • 178 Foundry tests (55 stQRL + 68 DepositPool + 55 ValidatorManager) — all passing
  • QRC-20 terminology used throughout docs and contract comments

Known blockers (not in scope)

Beacon deposit contract reverts on current testnet — documented in infrastructure/docs/validator-integration.md. Root cause is testnet infra, not QuantaPool contracts. New testnet expected soon.

Test plan

  • forge build — compiles with no errors
  • forge test — 178/178 passing, 0 failed
  • Contract logic peer-reviewed (deposit/withdrawal accounting, reward sync, validator state machine)
  • Docs verified against contract constants (VALIDATOR_STAKE, signature lengths, test counts)
  • Deploy to new Zond testnet when available

🤖 Generated with Claude Code

moscowchill and others added 19 commits January 23, 2026 11:58
- balanceOf() now returns raw shares (stable, tax-friendly)
- Added getQRLValue() for QRL equivalent display
- Exchange rate calculated via totalPooledQRL/totalShares
- Same security properties, cleaner tax implications

Community feedback: rebasing creates potential taxable events
- Lido and Rocket Pool for liquid staking designs
- The QRL Core Team for post-quantum blockchain infrastructure
- Robyer for fixed-balance token model feedback
Added comprehensive test coverage for:

stQRL-v2.sol (33 new tests):
- Approve function and events
- Transfer error paths (zero address, zero amount, insufficient balance)
- TransferFrom error paths (insufficient allowance, unlimited allowance)
- Pause affects transferFrom
- Mint/burn error paths and events
- Admin functions (transferOwnership, renounceOwnership)
- getQRLValue direct tests

DepositPool-v2.sol (38 new tests):
- Deposit error paths (stQRL not set, zero amount)
- Withdrawal error paths (zero shares, insufficient, already pending)
- Cancel withdrawal errors
- Validator funding errors and events
- Admin functions (setStQRL, setMinDeposit, emergencyWithdraw)
- Preview deposit
- Receive function and fundWithdrawalReserve
- Multi-user withdrawal queue
- Proportional reward distribution
- Slashing detection with events

Fixed test_SlashingReducesWithdrawalAmount which was previously empty.
Addresses critical security vulnerabilities identified by audit:

**H-01: First Depositor Share Inflation Attack (Donation Attack)**
- Added VIRTUAL_SHARES and VIRTUAL_ASSETS constants (1e3)
- Updated getSharesByPooledQRL() to use virtual offsets
- Updated getPooledQRLByShares() to use virtual offsets
- Updated getExchangeRate() for consistency
- This prevents attackers from manipulating share pricing in an empty pool

**H-02: Withdrawal Claim Accounting Discrepancy**
- Refactored claimWithdrawal() to burn shares FIRST
- Uses the actual burned QRL amount for all subsequent calculations
- Ensures reserve check, accounting, and transfer use consistent values
- Prevents potential insolvency from rate changes during claim

Test suite updated:
- Fixed mint/update order to match DepositPool behavior (mint first)
- Changed exact equality to approximate equality for QRL value assertions
- All 115 tests passing

Security: Virtual shares make donation attacks economically unviable by
creating a floor that ensures fair pricing even with near-empty pools.
M-03: Restrict emergencyWithdraw to only allow withdrawing excess balance
- Added ExceedsRecoverableAmount error
- Calculates recoverable amount: balance - totalPooledQRL - withdrawalReserve
- Prevents owner from draining user funds
- Added EmergencyWithdrawal event for transparency

M-04: Full 32-byte withdrawal credentials verification in fundValidator
- Verifies exact format: 0x01 + 11 zero bytes + contract address
- Uses assembly for efficient calldata loading
- Prevents validators from being funded with wrong withdrawal address

Additional changes:
- Multiple withdrawal requests per user (array-based storage)
- Added getWithdrawalRequestCount() helper function
- Added WithdrawalCancelled event
- Made setStQRL() one-time only (StQRLAlreadySet error)
- Removed unused WithdrawalPending error

All 118 tests passing (55 stQRL + 63 DepositPool)
…lash

M-1 audit finding: The status check happened AFTER changing status to
Slashed, so the condition was always false and activeValidatorCount
never decremented when slashing an active validator.

Fix: Cache previousStatus before modifying, then check cached value.

Also moves TestToken.sol to v1-deprecated (test helper, not protocol).
55 tests covering:
- Initialization and state
- Validator registration (success, auth, duplicates, invalid pubkey)
- Activation (single and batch)
- Exit request and completion
- Slashing with M-1 fix verification (counter decrements correctly)
- View functions (getValidator, getStats, getValidatorsByStatus)
- Admin functions (setDepositPool, transferOwnership)
- Full lifecycle tests
- Fuzz tests for registration and slashing counter correctness
…tate

N-1 audit finding: Counter was only decremented when slashing from Active
state, but Exiting validators also count toward activeValidatorCount.
This could leave the counter artificially high if validators were slashed
while in the exit queue.

Fix: Always decrement activeValidatorCount when slashing, since both
Active and Exiting states are included in the count.
- Move outdated research docs to v1-deprecated:
  - rocketpool-reading-guide.md (initial research)
  - minipool-economics.md (unused minipool concept)
  - quantapool-research.md (references 40k QRL, outdated)

- Add new docs/architecture.md reflecting current v2 implementation:
  - Fixed-balance token model (stQRL-v2)
  - Trustless reward sync (no oracle)
  - ValidatorManager lifecycle
  - 10,000 QRL validators
  - Security model and test coverage
Zond's mainnet_config.go specifies MaxEffectiveBalance: 40000 * 1e9,
not 10,000 as previously used. This matches the original v1 contracts.

Updated:
- DepositPool-v2.sol: VALIDATOR_STAKE = 40_000 ether
- ValidatorManager.sol: VALIDATOR_STAKE = 40_000 ether
- Test files: deposit amounts for validator funding tests
- docs/architecture.md: correct stake amount
QP-01: Add share locking to stQRL so users cannot transfer shares that
are pending withdrawal. DepositPool locks on request, unlocks on
claim/cancel. Adapted for array-based multi-request withdrawals —
checks unlocked balance before allowing new withdrawal requests.

QP-05: Add MIN_DEPOSIT_FLOOR (0.01 ether) so setMinDeposit cannot be
set to zero. Defense-in-depth on top of the existing virtual shares
inflation protection.
Replace constant MIN_DEPOSIT_FLOOR with adjustable minDepositFloor state
variable so the owner can lower the deposit minimum post-deployment if QRL
appreciates. Adds ABSOLUTE_MIN_DEPOSIT (0.001 QRL) as dust prevention.
…cture

Move Solidity contracts to contracts/solidity/, add Hyperion (.hyp) ports
under contracts/hyperion/ with pragma hyperion ^0.8.24. Update all test
import paths for the new layout.
The README was out of date — it didn't cover the infrastructure
(Terraform/Ansible), monitoring stack (Prometheus/Grafana/Alertmanager),
key management tooling, audit-driven tests, CI, or project structure.
Updated test count from 173 to 217, added completed roadmap items,
and expanded the architecture diagram and security section.

https://claude.ai/code/session_01JD9cmcCgf9dNcWVZ9CXbgj
- Fix VALIDATOR_STAKE (10k → 40k) and signature size (~2420 → 4595) in architecture.md
- Update test counts to match actual suite (178 tests across 3 suites)
- Replace ERC-20 with QRC-20 in docs and stQRL-v2.sol comments
- Remove 7 audit PoC test files (39 tests) — bugs are fixed, core suite covers regressions

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly upgrades the QuantaPool protocol by transitioning to a fixed-balance liquid staking token, enhancing security against common attacks, and introducing a dedicated contract for robust validator lifecycle management. It also expands the project's reach by integrating a Hyperion port layer, ensuring broader compatibility and future-proofing. The changes aim to provide a more stable, secure, and maintainable foundation for QRL liquid staking.

Highlights

  • Fixed-Balance stQRL Model: The stQRL token has been refactored from a rebasing model to a fixed-balance model, similar to wstETH. balanceOf() now returns stable shares, while getQRLValue() provides the fluctuating QRL equivalent, offering clearer tax implications.
  • Enhanced Security Measures: Implemented virtual shares (1e3) to prevent first-depositor inflation attacks, locked withdrawal shares to prevent transfers during the withdrawal queue, and an owner-adjustable minimum deposit floor for increased flexibility and security.
  • ValidatorManager Contract Integration: A new ValidatorManager contract has been introduced to track the full lifecycle of validators (Pending → Active → Exiting → Exited / Slashed), including Dilithium public key storage and batch activation capabilities.
  • Updated Validator Stake and Credentials: The VALIDATOR_STAKE constant has been corrected to 40,000 QRL to align with Zond mainnet configuration, and withdrawal credentials verification has been refined to ensure funds return correctly to the DepositPool.
  • Hyperion Port Layer Implementation: A Hyperion port layer has been added, including sync-hyperion.js to generate .hyp mirrors from Solidity sources, along with dedicated compile and deploy scripts for Zond, facilitating multi-platform compatibility.
  • Comprehensive Testing and Documentation: The project now boasts 178 Foundry tests covering stQRL, DepositPool, and ValidatorManager logic, all passing. Additionally, contracts have been reorganized into contracts/solidity/ with v1 contracts deprecated, and documentation has been updated to reflect the new architecture and QRC-20 terminology.
Changelog
  • .gitignore
    • Added entries for Hyperion artifacts and findings directories.
  • README.md
    • Updated overview to reflect the fixed-balance token model.
    • Added new key features including production infrastructure and monitoring stack.
    • Detailed the new project structure with reorganized directories.
    • Explained the fixed-balance model with an example.
    • Added sections for infrastructure and monitoring.
    • Updated development prerequisites and workflow for Hyperion.
    • Increased test coverage count to 178 and detailed new test areas.
    • Updated roadmap items to reflect completed tasks.
    • Added security mitigations for first-depositor attacks.
    • Included acknowledgments for community feedback and pioneering projects.
  • config/testnet-hyperion.json
    • Added new file for Hyperion testnet deployment configuration.
  • contracts/solidity/DepositPool-v2.sol
    • Updated IstQRL interface to include share locking/unlocking and locked shares query functions.
    • Corrected VALIDATOR_STAKE constant to 40,000 ether.
    • Added ABSOLUTE_MIN_DEPOSIT and minDepositFloor constants.
    • Changed withdrawalRequests mapping to support multiple requests per user via an array.
    • Added nextWithdrawalIndex to track processed withdrawal requests.
    • Introduced new events: WithdrawalCancelled, MinDepositFloorUpdated, StQRLSet, EmergencyWithdrawal.
    • Added new error types: BelowMinDepositFloor, BelowAbsoluteMin, StQRLAlreadySet, InvalidWithdrawalIndex, ExceedsRecoverableAmount.
    • Removed WithdrawalPending error.
    • Updated constructor to set minDeposit to 100 ether.
    • Modified requestWithdrawal to lock user shares and support multiple requests, returning a requestId.
    • Revised claimWithdrawal to process multiple requests in FIFO order, use request-time QRL value, and unlock shares.
    • Modified cancelWithdrawal to accept a requestId and unlock shares.
    • Added getWithdrawalRequestCount function to query total and pending withdrawal requests.
    • Updated fundValidator comments and refined withdrawal_credentials verification logic.
    • Changed fundWithdrawalReserve to be onlyOwner and reclassify funds from totalPooledQRL.
    • Added setMinDepositFloor function to allow owner to adjust the minimum deposit floor.
    • Enhanced emergencyWithdraw to only allow withdrawal of excess funds not part of pooled QRL or withdrawal reserve.
    • Modified receive function to no longer auto-classify incoming funds into the withdrawal reserve.
  • contracts/solidity/ValidatorManager.sol
    • Corrected VALIDATOR_STAKE constant to 40,000 ether.
    • Adjusted markValidatorSlashed logic to correctly decrement activeValidatorCount when a validator is slashed from either Active or Exiting status.
  • contracts/solidity/stQRL-v2.sol
    • Updated contract title, notice, and dev comments to reflect the new fixed-balance token model.
    • Added VIRTUAL_SHARES and VIRTUAL_ASSETS constants to prevent first-depositor attacks.
    • Introduced _lockedShares mapping to track shares locked for withdrawals.
    • Removed the TransferShares event.
    • Added InsufficientUnlockedShares error.
    • Modified totalSupply(), balanceOf(), and allowance() to directly return share amounts.
    • Added getQRLValue() function to return the QRL equivalent of an account's shares.
    • Updated getSharesByPooledQRL() and getPooledQRLByShares() to incorporate virtual offsets for accurate conversion.
    • Updated getExchangeRate() to use virtual offsets for consistency.
    • Modified mintShares() and burnShares() to emit the standard Transfer event with share amounts.
    • Updated updateTotalPooledQRL() dev comment to clarify its impact on the exchange rate.
    • Added lockShares(), unlockShares(), and lockedSharesOf() functions for managing locked shares during withdrawals.
    • Modified _transfer internal function to check for sufficient unlocked shares before transfer.
    • Adjusted _approve internal function to work directly with share amounts.
  • contracts/solidity/v1-deprecated/DepositPool.sol
    • Renamed file to reflect its deprecated status and new directory structure.
  • contracts/solidity/v1-deprecated/OperatorRegistry.sol
    • Renamed file to reflect its deprecated status and new directory structure.
  • contracts/solidity/v1-deprecated/RewardsOracle.sol
    • Renamed file to reflect its deprecated status and new directory structure.
  • contracts/solidity/v1-deprecated/TestToken.sol
    • Renamed file to reflect its deprecated status and new directory structure.
  • contracts/solidity/v1-deprecated/stQRL.sol
    • Renamed file to reflect its deprecated status and new directory structure.
  • docs/architecture.md
    • Added new file detailing the QuantaPool v2 architecture, including diagrams, core contract descriptions, security model, Zond-specific adaptations, test coverage, and deployment checklist.
  • docs/v1-deprecated/minipool-economics.md
    • Renamed file to reflect its deprecated status and new directory structure.
  • docs/v1-deprecated/quantapool-research.md
    • Renamed file to reflect its deprecated status and new directory structure.
  • docs/v1-deprecated/rocketpool-reading-guide.md
    • Renamed file to reflect its deprecated status and new directory structure.
  • hyperion/README.md
    • Added new file providing an overview of Hyperion sources, workflow, and notes.
  • hyperion/contracts/DepositPool-v2.hyp
    • Added new file, a generated Hyperion mirror of DepositPool-v2.sol.
  • hyperion/contracts/ValidatorManager.hyp
    • Added new file, a generated Hyperion mirror of ValidatorManager.sol.
  • hyperion/contracts/stQRL-v2.hyp
    • Added new file, a generated Hyperion mirror of stQRL-v2.sol.
  • hyperion/test/DepositPool-v2.t.hyp
    • Added new file, a generated Hyperion mirror of DepositPool-v2.t.sol.
  • hyperion/test/ValidatorManager.t.hyp
    • Added new file, a generated Hyperion mirror of ValidatorManager.t.sol.
  • hyperion/test/stQRL-v2.t.hyp
    • Added new file, a generated Hyperion mirror of stQRL-v2.t.sol.
  • package.json
    • Added new npm scripts: compile:solidity, sync:hyperion, compile:hyperion, and deploy:hyperion.
  • scripts/compile-hyperion.js
    • Added new script to compile Hyperion .hyp sources, ensuring compiler availability, clearing artifacts, and generating a manifest.
  • scripts/compile.js
    • Updated the contractsDir path to contracts/solidity.
  • scripts/deploy-hyperion.js
    • Added new script to deploy Hyperion contracts to Zond testnet, including loading configuration, artifacts, and linking contracts.
  • scripts/sync-hyperion.js
    • Added new script to synchronize Solidity contract and test files to Hyperion .hyp format, updating pragmas and import paths.
  • test/DepositPool-v2.t.sol
    • Updated import paths for stQRL-v2.sol and DepositPool-v2.sol.
    • Adjusted test_MultipleDeposits to use 200 ether for user2.
    • Updated test_DepositAfterRewards assertions to reflect fixed-balance model and virtual shares.
    • Updated test_SyncRewards_DetectsRewards assertions for fixed-balance model.
    • Modified test_RequestWithdrawal to return requestId and updated assertions.
    • Revised test_ClaimWithdrawal to request withdrawal before funding reserve and updated assertions.
    • Updated test_ClaimWithdrawal_TooEarly to reflect new withdrawal flow.
    • Modified test_CancelWithdrawal to accept requestId.
    • Updated test_WithdrawalAfterRewards assertions for fixed-balance model and virtual shares.
    • Added test_SlashingReducesWithdrawalAmount to simulate slashing and verify reduced withdrawal amount.
    • Added test_SlashingDetected_EmitsEvent to verify slashing event emission.
    • Updated test_CanFundValidator and test_FundValidatorMVP to use 40,000 QRL stake.
    • Updated test_GetPoolStatus assertions for fixed-balance model.
    • Added new tests for Deposit_StQRLNotSet_Reverts, Deposit_ZeroAmount_Reverts, Deposit_EmitsEvent.
    • Added new tests for RequestWithdrawal_ZeroShares_Reverts, RequestWithdrawal_InsufficientShares_Reverts, MultipleWithdrawalRequests, RequestWithdrawal_WhenPaused_Reverts, RequestWithdrawal_EmitsEvent.
    • Added new tests for ClaimWithdrawal_NoRequest_Reverts, ClaimWithdrawal_EmitsEvent.
    • Added new tests for CancelWithdrawal_NoRequest_Reverts.
    • Added new tests for FundValidatorMVP_InsufficientBuffer_Reverts, FundValidatorMVP_EmitsEvent.
    • Added new tests for SetStQRL, SetStQRL_ZeroAddress_Reverts, SetStQRL_NotOwner_Reverts, SetStQRL_AlreadySet_Reverts.
    • Added new tests for SetMinDeposit, SetMinDeposit_NotOwner_Reverts, SetMinDeposit_EmitsEvent.
    • Added new tests for Unpause, Unpause_NotOwner_Reverts.
    • Added new tests for TransferOwnership, TransferOwnership_ZeroAddress_Reverts, TransferOwnership_NotOwner_Reverts, TransferOwnership_EmitsEvent.
    • Added new tests for EmergencyWithdraw, EmergencyWithdraw_ExceedsRecoverable_Reverts, EmergencyWithdraw_ZeroAddress_Reverts, EmergencyWithdraw_ZeroAmount_Reverts, EmergencyWithdraw_NotOwner_Reverts.
    • Added new tests for PreviewDeposit, PreviewDeposit_AfterRewards, PreviewDeposit_StQRLNotSet.
    • Added new tests for Receive_IsNoOp, Receive_DetectedAsRewardsBySyncRewards.
    • Added new tests for FundWithdrawalReserve, FundWithdrawalReserve_EmitsEvent.
    • Added new tests for MultipleUsersWithdrawalQueue, RewardsDistributedProportionally.
    • Added new tests for SetMinDepositFloor, SetMinDepositFloor_BelowAbsoluteMin_Reverts, SetMinDepositFloor_NotOwner_Reverts, SetMinDepositFloor_EmitsEvent, SetMinDeposit_AfterFloorLowered.
    • Updated event declarations to include new events.
  • test/ValidatorManager.t.sol
    • Updated VALIDATOR_STAKE constant to 40,000 ether.
    • Corrected markValidatorSlashed logic to decrement activeValidatorCount when a validator is slashed from either Active or Exiting status, verifying the M-1 fix.
  • test/stQRL-v2.t.sol
    • Updated import path for stQRL-v2.sol.
    • Modified contract title and notice to reflect fixed-balance token.
    • Removed TransferShares event declaration.
    • Updated test_FirstDeposit_OneToOneRatio to reflect fixed-balance model and virtual shares.
    • Updated test_RewardsIncreaseQRLValue and test_SlashingDecreasesQRLValue to reflect fixed-balance model and virtual shares.
    • Updated test_MultipleUsers_RewardDistribution assertions for fixed-balance model and virtual shares.
    • Updated test_ShareConversion_AfterRewards assertions for fixed-balance model and virtual shares.
    • Updated test_ZeroPooled_ZeroTotalShares to reflect virtual shares ensuring 1:1 ratio.
    • Updated test_LargeNumbers and test_SmallNumbers assertions for fixed-balance model and virtual shares.
    • Renamed testFuzz_RebasingMath to testFuzz_ExchangeRateMath and updated assertions for fixed-balance model and virtual shares.
    • Updated test_Transfer and test_TransferAfterRewards assertions for fixed-balance model.
    • Updated test_TransferFrom assertions for fixed-balance model.
    • Added new tests for Approve, Approve_ZeroAddress_Reverts, Approve_EmitsEvent.
    • Added new tests for Transfer_ToZeroAddress_Reverts, Transfer_ZeroAmount_Reverts, Transfer_InsufficientBalance_Reverts, Transfer_EmitsEvent.
    • Added new tests for TransferFrom_ZeroAmount_Reverts, TransferFrom_InsufficientAllowance_Reverts, TransferFrom_UnlimitedAllowance, TransferFrom_WhenPaused_Reverts.
    • Added new tests for MintShares_ToZeroAddress_Reverts, MintShares_ZeroAmount_Reverts, MintShares_WhenPaused_Reverts, MintShares_EmitsEvents.
    • Added new tests for BurnShares_FromZeroAddress_Reverts, BurnShares_ZeroAmount_Reverts, BurnShares_InsufficientBalance_Reverts, BurnShares_WhenPaused_Reverts, BurnShares_EmitsEvents, BurnShares_ReturnsCorrectQRLAmount.
    • Added new tests for SetDepositPool_ZeroAddress_Reverts.
    • Added new tests for TransferOwnership, TransferOwnership_ZeroAddress_Reverts, TransferOwnership_NotOwner_Reverts, TransferOwnership_EmitsEvent.
    • Added new tests for RenounceOwnership, RenounceOwnership_NotOwner_Reverts, RenounceOwnership_EmitsEvent.
    • Added new tests for OnlyOwnerCanPause, OnlyOwnerCanUnpause.
    • Added new tests for GetQRLValue_ReturnsCorrectValue, GetQRLValue_ZeroShares.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

The pull request refactors the QuantaPool liquid staking protocol from a rebasing to a fixed-balance token model, introducing virtual shares to prevent first-depositor attacks and updating the withdrawal mechanism to support multiple requests per user. Key changes include modifying stQRL-v2.sol to return stable shares via balanceOf() and a fluctuating QRL equivalent via getQRLValue(), and enhancing DepositPool-v2.sol to manage a queue of withdrawal requests, lock shares during the request phase, and improve the emergencyWithdraw function. The ValidatorManager.sol contract was updated to correctly decrement the active validator count upon slashing. Documentation (README.md, docs/architecture.md) and test files were updated to reflect these changes, and new Hyperion-related files were added for cross-chain compatibility. A review comment highlights a discrepancy where the documentation incorrectly states shares are burned during withdrawal requests instead of locked, and another points out a potential denial-of-service vulnerability in the claimWithdrawal function due to an unbounded loop for skipping cancelled requests, which could lead to out-of-gas issues.


**Withdrawal Flow:**
1. User calls `requestWithdrawal(shares)`
2. Shares burned, QRL amount calculated
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The description of the withdrawal flow states that shares are burned during the request. However, in the implementation, shares are only locked at this stage and are burned later during the claim. This could be misleading for developers and auditors. I recommend updating this step to clarify that shares are locked, not burned, upon request.

Comment on lines +336 to +338
while (requestIndex < totalRequests && withdrawalRequests[msg.sender][requestIndex].shares == 0) {
requestIndex++;
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The while loop to skip cancelled withdrawal requests could lead to a denial-of-service condition if a user has a large number of consecutive cancelled requests. The transaction could run out of gas, preventing the user from claiming any subsequent valid withdrawals. Consider adding a limit to the number of iterations or allowing the user to specify a starting index to claim from to mitigate this potential issue.

- architecture.md: shares are locked at request time, burned at claim (not burned at request)
- DepositPool-v2.sol: add comment clarifying the cancelled-request skip loop is self-bounded

Addresses Gemini Code Assist review comments on PR #12.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@moscowchill moscowchill merged commit 5b556da into main Mar 12, 2026
2 checks passed
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.

2 participants