Banked from etherfi-protocol/beHYPE @ 06ee135 (WALK). First HyperEVM target in the library. HYPE liquid staking: StakingCore reads HyperCore via l1Read precompiles + writes via CoreWriter.
0x0000...0800-0810: position(0800), spotBalance(0801), vaultEquity(0802), withdrawable(0803), delegations(0804), delegatorSummary(0805), markPx(0806), oraclePx(0807), spotPx(0808), L1BlockNumber(0809), ... (read side, staticcall). WRITES go through CoreWriter at 0x3333...3333 via _encodeAction(actionId, abi.encode(...)): delegate(3), depositToStaking(4), withdrawFromStaking(5), spotSend/withdraw(6). The native HYPE system contract is 0x2222...2222. HyperCore uses 8 decimals; HyperEVM uses 18 -> conversions everywhere.delegatorSummary(address(this)) returns the protocol's OWN delegated/undelegated/pendingWithdrawal; spotBalance(address(this), HYPE_TOKEN_ID) its own spot. These are the protocol's own account state - an attacker cannot alter them (only DONATE HYPE to the protocol's account, which raises the read = benefits holders, not an attack).beHYPE's stake/withdraw use a STORED exchangeRatio, NOT a live getTotalProtocolHype() read:
- stake() mints HYPEToBeHYPE(msg.value) = msg.value*1e18/exchangeRatio (stored).
- BeHYPEToHYPE/HYPEToBeHYPE use stored exchangeRatio.
- Only updateExchangeRatio() reads the live getTotalProtocolHype() (= delegatorSummary + spotBalance + EVM balance), and it is TRIPLE-guarded: PROTOCOL_ADMIN-only, MIN_BLOCKS_BEFORE_EXCHANGE_RATIO_UPDATE since the last HyperCore op (lastHyperCoreOperationBlock, so the read sees SETTLED HyperCore state, not mid-operation), and an APR cap (yearlyRateInBps > acceptablAprInBps -> revert when exchangeRateGuard on).
=> Even if getTotalProtocolHype could be transiently moved, it does NOT move the stake/withdraw rate (stored), and the admin update is rate-bounded + settle-delayed. This is the CORRECT way to consume a manipulable/HyperCore-sourced TVL into an LST rate. Audit reflex on any HyperEVM/precompile-priced LST: does stake/withdraw read the precompile LIVE (manipulable -> donation/flash attack) or a STORED admin-bounded rate (safe)? beHYPE = stored+bounded = safe. (Same family as [[2026-06-21-cycle267-lst-rate-source-bifurcation-and-lazy-slash-arb-bounds]] done right; the MIN_BLOCKS settle-delay is the HyperEVM-specific addition - read HyperCore only after the cross-VM op finalizes.)
lastHyperCoreOperationBlock + MIN_BLOCKS) is HyperEVM-specific and load-bearingHyperCore<->HyperEVM ops (deposit/withdraw/stake/unstake/delegate) are not instantly reflected in the precompile reads (cross-VM settlement). beHYPE records lastHyperCoreOperationBlock = block.number on every CoreWriter op and forbids updateExchangeRatio until MIN_BLOCKS later. Audit lens for HyperEVM: any contract that WRITES to HyperCore then READS a precompile in a value-bearing way MUST wait for settlement, else it reads stale/mid-flight state. Missing settle-delay between a CoreWriter action and a precompile read = a real bug on HyperEVM.
_convertTo8Decimals(x) = x/1e10 (truncates, used when SENDING to HyperCore), _convertTo18Decimals(x) = x*1e10 (reading back). Truncation-on-send leaves <1e10 wei dust in the EVM contract, which is still counted in address(this).balance within getTotalProtocolHype -> not lost. Audit reflex: check that the 8<->18 truncation dust is retained+counted (not silently dropped) and that mixed-precision sums (_convertTo18Decimals(hyperCore8dec) + evmBalance18dec) don't double-scale.
beHYPE has BOTH an instant-withdrawal path (draws live address(stakingCore).balance - lowWatermark, rate-limited) and a standard queue (reserves hypeRequestedForWithdraw). The instant path's liquidity check does NOT subtract hypeRequestedForWithdraw -> instant withdrawers can drain liquid HYPE reserved for the queue (bounded by low-watermark + bucket limiter; queue is later refunded from HyperCore by admin, so it's a liveness/priority gap, not theft). CONTRAST: the SAME team's EtherFiRedemptionManager.getInstantLiquidityAmount (cash/main) DOES subtract both queue locks ([[2026-06-21-cycle267-dual-withdrawal-queue-shared-liquidity-union-bound]]). Bank: when one product subtracts a reservation and a sibling product by the same team does not, the inconsistency is the lead - check whether the instant/permissionless drain nets the queued reservation in EVERY product.
WithdrawManager.withdraw locks hypeAmount at request-rate, ESCROWS the beHYPE (transferFrom into the WM, NOT burned), burns at finalizeWithdrawals. Escrow-then-delayed-burn == burn-at-request for double-spend safety (the escrow prevents reuse/transfer). Bankable positive.getTotalProtocolHype() >= sum(queued hypeAmount); safe only while the rate is APR-bounded (slashes slow/bounded/visible). Same slow-union-bound class as the main repo; bounded -> WALK, flag as "queue backing is an operational invariant, no hard solvency assert."VERDICT pattern for HyperEVM LSTs: precompile-read manipulation is defeated by stored+bounded+settle-delayed rates; the residuals are reservation-accounting (instant vs queue) and solvency-assert gaps, both bounded by admin pacing + the APR guard. Confirm exchangeRateGuard is enabled in production before treating the rate-bound-dependent items as live. Related: [[2026-06-10-cycle213-restaking-slash-vs-withdrawal-epoch-union-bound]], [[2026-06-21-cycle267-snapshot-postcondition-safety-net-for-new-entry-paths]].