Skip to content
$1,000,000 in security audit grants are live now, Apply here →

Security review · November 2025

Staking Modules

for Valantis

Valantis engaged Guardian to review the security of their Valantis Staking Modules Review. From the 10th of November to the 12th of November, a team of 2 auditors reviewed the source code in scope.

Published
Review window
November 10 to 12, 2025
Rounds
Main Review, Remediation Review
Language
Solidity
Chains
Hyperliquid
Sector
DEXs and AMMs, Staking
  • 0 Critical
  • 1 High
  • 0 Medium
  • 0 Low
  • 6 Informational

5 resolved · 2 acknowledged

Scope

Overview

Valantis engaged Guardian to review the security of their Valantis Staking Modules Review. From the 10th of November to the 12th of November, a team of 2 auditors reviewed the source code in scope.

Findings 7

Main Review

6 findings
  1. H-01 High Reverting Burn Recipient Bricks Future Redeems DoS Resolved
    Location
    Overseer.sol
    Round
    Main Review

    Description

    Proof of concept: PoC

    Overseer.burn blindly accepts any to address and simply pushes the request into the burn queue. When someone later calls redeem, the protocol sends native HYPE to the original user and requires the low-level call to succeed.

    The queue gating logic _redeemable insists that the contract holds enough idle Hype to cover every previous burn plus the current one. A stuck entry therefore permanently consumes the whole allowance.

    An attacker can mint stHYPE, burn it to a contract whose fallback always reverts (or can be toggled to revert) and call redeem. The transfer never succeeds, so completed stays false, redeemed never increases and the jammed burn keeps its amount inside difference.

    Because difference + protocolPendingFee must stay ≤ Overseer's idle Hype, any honest user who burns afterwards immediately hits NotRedeemable until governance sources extra liquidity. The attacker can later flip their recipient to accept Hype and exit, so the only cost is temporarily parking capital while everyone else remains blocked.

    A dedicated Forge test test/OverseerBurnQueueJammed.t.sol demonstrates the failure end-to-end: a malicious burner locks a 20 Hype burn and a subsequent 30 Hype burn by an honest user reverts until the protocol withdraws fresh Hype from staking modules.

    Impact: One reverting recipient can freeze withdrawals for all users, forcing the protocol to keep matching idle liquidity on hand or rely on manual intervention to unblock the queue.

    Recommendation

    Instead of a low level call to transfer the raw Hype use SafeTransferLib.forceSafeTransferETH. This way, this transfer can never revert.

    Resolution

    Valantis Team: The issue was resolved in commit 6742792.

  2. I-01 Informational SMEM Temporary Underreports Balance Warning Resolved
    Location
    StakingModuleExternalManagement.sol
    Round
    Main Review

    Description

    StakingModuleExternalManagement.getTotalBalance() only sums the module’s HyperCore spot balance and EVM balance together with the stake account’s staking balance. Any funds that temporarily sit in the stake account’s HyperCore spot balance or are mid-bridge are invisible to this view. That “limbo” period occurs twice.

    First, immediately after deposit() the module performs CoreWriterLib.spotSend, which merely enqueues a Core transaction in the current block: the system address already holds the HYPE in EVM, but Core has not yet credited the stake account’s balance, so getTotalBalance() still reads the pre-deposit value.

    Overseer tries to protect against same-block mistakes by setting stakingModuleLastBlockInteraction inside every deposit/withdraw call and rejecting rebase() in the same block via RebaseLocked, so a deposit and rebase cannot co-exist within one block.

    However, there is still at least one full block between the moment funds leave Overseer and the moment Core processes the queued spotSend, and during that block getTotalBalance() continues to show the old value even though native HYPE already left the system. Later, when the external operator moves the stake account’s spot balance into staking, the same blind spot reappears because the module never queries that spot balance.

    Likewise during withdrawals, undelegated funds live in the stake account’s spot balance until the operator forwards them back to the module’s HyperCore account, leaving another window where the backing exists but is untracked.

    This creates two problems:

    • Overseer.getNewSupply() aggregates getTotalBalance() for every module. If a deposit or withdrawal straddles the block

    boundary between “Overseer already sent HYPE” and “Core has credited the new balance,” the reported supply dips while the real assets remain elsewhere. Rebasing during that limbo block fabricates a supply decrease (or subsequent spike) that impacts every stHYPE holder even though it stems from sequencing rather than economics.

    • maxRedeemable = balance - totalLiability inherits the same miscount, so large burns queued during a limbo block can be

    rejected even though HYPE is already en route, again letting timing-sensitive actors grief redemptions.

    Recommendation

    Consider maintaining a per-block accumulator that adds “limbo” amounts (deposits that have bridged out but not yet hit Core, or withdrawals that have been undelegated but not yet forwarded) and include it inside getTotalBalance() until the corresponding Core transaction settles.

    At minimum, encode sequencing rules: e.g., manager should never submit rebase() in the same block as deposit()/requestWithdraw(), so operational scripts cannot accidentally front-run themselves. Either solution turns the temporary mismatch into an accounted liability so supply math and redeemability checks stay monotonic within a block.

    Resolution

    Valantis Team: The issue was resolved in commit 2d4a1a1.

  3. I-02 Informational SMEM Does Not Emit Any Event Best Practices Resolved
    Location
    StakingModuleExternalManagement.sol
    Round
    Main Review

    Description

    StakingModuleExternalManagement mutates protocol-owned balances (bridging deposits, initiating withdrawals, forwarding native HYPE) without emitting any events. Neither deposit, requestWithdraw, nor withdraw emit structured logs about the amounts, stake account, HyperCore account, or initiating manager.

    Even the receive() fallback, which accepts native transfers from previously requested withdrawals, is silent. This makes it impossible for off-chain monitoring, accounting, or incident response to reconstruct capital flows: e.g., when HYPE disappears from Overseer during a deposit, there is no corresponding event proving where it went or whether the stake account acknowledged receipt.

    Likewise, withdrawals leave no traces except balance deltas. Since the module hands custody to an external multisig, not emitting events deprives governance and on-chain monitors of the basic audit trail needed to confirm that off-chain agreements are being honored.

    Recommendation

    Emit structured events for every state-changing action (Deposit, RequestWithdraw, Withdraw) and log inbound HYPE in receive(). Include the manager, stakeAccount, HyperCore account and amount so off-chain indexers can reconcile movements across Overseer, the module, and HyperCore.

    Even simple events (e.g., event Deposit(address indexed manager, uint256 amount) and event HyperCoreFundsReceived(uint256 amount)) would provide the minimum observability needed to detect stuck transfers or misbehavior by the external operator.

    Resolution

    Valantis Team: The issue was resolved in commit 5d61e22.

  4. I-03 Informational No Plan For Aligned Quote Assets Documentation Acknowledged
    Location
    StakingModuleExternalManagement.sol
    Round
    Main Review

    Description

    The protocol plan explicitly assigns 200k HYPE to a StakingModuleExternalManagement instance “to whitelist a quote asset,” implying the module will satisfy Hyperliquid’s aligned-quote/stable requirements.

    However, there is no contract code, config or documented runbook that handles the 1M HYPE stake (200k base + 800k alignment bond), the 50% reserve-yield kickback, or the validator-voted compliance checks described in Hyperliquid’s spec:

    (https://hyperliquid.gitbook.io/hyperliquid-docs/hypercore/aligned-quote-assets).

    Today’s module just forwards deposits to a generic stakeAccount and trusts it to “whitelist a quote asset.” That may be acceptable if alignment is explicitly out of scope, but the docs already describe a three-year lock and extra yield justified by quote-asset whitelisting, so readers will naturally assume the module is pursuing alignment unless the team says otherwise.

    Without instrumentation showing that the extra bond, revenue share, and native minting actually happened, governance and users cannot tell whether the promised fee discounts will ever materialize even though capital is locked under that assumption.

    Recommendation

    Add documentation (and, if needed, supporting code) that explains how this staking module is supposed to meet Hyperliquid’s aligned-quote requirements before user funds are committed to that use case.

    Resolution

    Valantis Team: Acknowledged.

  5. I-04 Informational Withdrawal Amounts Must Be In Wei Documentation Resolved
    Location
    StakingModuleExternalManagement.sol: 260
    Round
    Main Review

    Description

    The requestWithdraw contains an array of amounts. According to the natspec, this is Array of HYPE amounts to withdraw from each account.

    However, the CoreWriterLib.spotSend expects an amount in Wei units and not EVM amount (18 decimals). The natspec does not clearly state the units of this amount param and could cause confusion or incorrect bridged amounts.

    Recommendation

    Make sure the documentation explicitly states that the HYPE amounts should be in Wei and not Evm amounts.

    Resolution

    Valantis Team: The issue was resolved in commit 164467d.

  6. I-05 Informational Incorrect StHYPE Supply Adjustment Validation Acknowledged
    Location
    StakingModuleExternalManagement.sol: 161
    Round
    Main Review

    Description

    The StakingModuleExternalManagement.getTotalBalance() contains a note that warns manager not to call rebase in the following cases to avoid stHYPE supply adjustments:

    • stake account has not deposited the received HYPE into its staking balance
    • the stake account's stake balance has been unstaked into spot balance, but not yet sent to this

    contract's HyperCore spot balance

    However, the rebase function only prevents executing it in the same block as the last module interaction, and does not check for the staking account HYPE spot balance.

    Recommendation

    Make sure rebase will wait for any pending tx or transitory state, adding validations in the off chain services.

    Resolution

    Valantis Team: Acknowledged.

Remediation Review

1 finding
  1. I-01 Informational Receive Function Contains Extra Code Informational Resolved
    Location
    StakingModuleExternalManagement.sol: 183
    Round
    Remediation Review

    Description

    The StakingModuleExternalManagement.receive function, now emits HyperCoreFundsReceived event. When bridging from Core, the system address will send HYPE to the contract, with a gas limit of 30,000 gas.

    Currently, receiving HYPE and emitting the event will consume around 22k gas. In case that extra code is added to the receive function, bridging from Core can be blocked.

    Recommendation

    Document this behavior in the contract, to make sure extra care is taken when adding more code in the receive function.

    Resolution

    Valantis Team: The issue was resolved in commit 9d52ae3.

More from Valantis

  1. Overseer

    24 findings1 high 24 findings: 1 high, 2 medium, 4 low, 17 informational

Put your code through the same review.

This review started with a conversation about scope. Tell us what you are building and we will plan yours with you.

Get a quote