Add missing require_current_state guards - #466
Merged
abayomicornelius merged 2 commits intoAug 24, 2026
Merged
Conversation
|
@abayomiwav Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
require_current_state is enforced at the top of the large majority of investment_vault's public and internal functions (30+ call sites), as the safety net that rejects calls made against a stale storage-layout version after a contract upgrade. Five functions in this file were silently missing it despite being exactly the kind of state-mutating, capital-sensitive operations the guard exists to protect: - set_wormhole_core — configures who is trusted to authorize minting HBS via the Wormhole bridge path; its sibling set_bridge already had the guard, this one didn't. - fund_project_internal — the vault's primary capital-deployment path, reached via fund_project, fund_project_with_approvals, and batch_fund_projects. None of those three entry points checked this guard anywhere in their call chain before reaching this function. - receive_yield_internal — records yield receipts and updates investor accounting. - claim_insurance_internal — pays out insurance claims against a project's collateral. - calculate_carbon_credits — its two siblings in the same feature, issue_carbon_credits and transfer_carbon_credits, both already checked this guard; this one didn't. Without the guard, all five remain callable (and able to mutate storage or move funds) even after an upgrade has changed the storage layout in a way every other function in the file is protected against.
…project certify_project calls require_not_paused but never require_current_state, unlike every one of its neighbors that mutates project state — create_project, archive_project, update_impact_score, deposit_collateral, release_collateral, and set_creator_reputation all check both. Without the guard, certify_project stays callable and able to mutate Project(id).certification_status even against a stale storage layout after an upgrade, the same class of gap just fixed for investment_vault in the previous commit.
abayomiwav
force-pushed
the
fix/require-current-state-guard-gaps
branch
from
August 24, 2026 19:39
9d08283 to
646e9a7
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
require_current_stateis the guard that rejects a call made against a stale storage-layout version after a contract upgrade — it's already enforced at the top of the large majority of state-mutating functions across both contracts (30+ call sites ininvestment_vaultalone). Six functions across the two contracts were silently missing it, despite being exactly the kind of state-mutating, capital-sensitive operations the guard exists to protect. In every case, a sibling function performing the same class of operation already has the guard, which is how each gap was found — by diffing each function against its nearest neighbor.What's fixed
investment_vault:set_wormhole_core— configures who is trusted to authorize minting HBS via the Wormhole bridge path. Its siblingset_bridgealready had the guard; this one didn't.fund_project_internal— the vault's primary capital-deployment path, reached viafund_project,fund_project_with_approvals, andbatch_fund_projects. None of those three public entry points checked this guard anywhere in their call chain before reaching this function.receive_yield_internal— records yield receipts and updates investor accounting.claim_insurance_internal— pays out insurance claims against a project's collateral.calculate_carbon_credits— its two siblings in the same feature,issue_carbon_creditsandtransfer_carbon_credits, both already checked this guard; this one didn't.project_registry:certify_project— callsrequire_not_pausedbut neverrequire_current_state, unlike every other function that mutates project state (create_project,archive_project,update_impact_score,deposit_collateral,release_collateral,set_creator_reputation).Why it matters
Without the guard, each of these six functions remains callable — and able to mutate storage or move funds — even after an upgrade has changed the storage layout in a way every other function in the same contract is already protected against.
fund_project_internalin particular is the highest-value gap: it's the vault's single largest capital-deployment path, and none of its three public wrappers filled in for the missing check.Fix approach
Minimal and targeted — each function gets exactly the one-line guard call its siblings already have, added at the top before any other logic runs. No behavior changes beyond closing this gap; no new tests added since this mirrors an existing, already-tested guard pattern used identically elsewhere in both files.
Commits
investment_vault: add missing require_current_state guards— the fiveinvestment_vaultfunctions.project_registry: add missing require_current_state guard to certify_project— the oneproject_registryfunction.Closes #460
Closes #461
Closes #462
Closes #463