> For the complete documentation index, see [llms.txt](https://docs.buoy.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.buoy.finance/protocol-deep-dive/security-review-remediation.md).

# Security Review Remediation

Buoy's contracts were reviewed by [Shieldify](https://www.shieldify.org/). The review reported **7 Medium and 5 Low** severity findings — the full report is available here: [Buoy-Security-Review.pdf](https://github.com/buoyloan/buoy-docs/tree/main/.gitbook/assets/Buoy-Security-Review.pdf). All 12 findings were triaged: **9 were fixed** and **3 were deliberately dispositioned**, with rationale below.

All contract fixes are covered by the test suite (198 tests in `buoy-contracts`, all passing) and are fully backward compatible with already-deployed vault clones. Fixes in `BuoyVault` ship with a new implementation and apply to newly created vaults; `Router` fixes apply in place via UUPS upgrade.

## Fixed — 9 of 12

| ID       | Finding                                                                                                                                | Remediation                                                                                                                                                                                                                                                                                                                                                                          |
| -------- | -------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **M-02** | Cancelling a Locked withdrawal re-minted the original shares after NAV changes                                                         | Locked cancel now mints `min(original shares, owedUsdc repriced at the current share price)` — the free option (NAV drops → keep the USDC claim, NAV rallies → cancel back into shares) is gone.                                                                                                                                                                                     |
| **M-03** | Donating 1 wei of shares to the vault blocked `setRouter` forever                                                                      | New `pendingWithdrawalShares` counter tracks legitimate withdrawal escrow; `setRouter` gates on it instead of the externally inflatable `balanceOf(vault)`.                                                                                                                                                                                                                          |
| **M-04** | Every request bumped `interactionNonce` → settlement could be DoS'ed by front-running fulfiller transactions for 0.01 HYPE per request | Requests no longer bump the nonce. They are NAV-neutral: a deposit grows the EVM balance and `pendingDepositsUsdc` by the same amount (net zero in `hc + evm - pending`), and withdrawal escrow doesn't touch supply. The griefing vector is eliminated entirely.                                                                                                                    |
| **M-05** | A request with an impossible `minShares`/`minOut` plus a refusal to cancel = permanent `setRouter` blockade                            | The vault owner (protocol admin) may cancel any request after the timeout; funds always return to the original requester — this changes who may unlock, never where value flows.                                                                                                                                                                                                     |
| **M-06** | A stale high-water mark after a full wind-down suppressed the leader's fees in the next capitalization                                 | The bootstrap branch (`supply == 0`) resets `highWaterMark = PRICE_SCALE`, giving each capitalization a fresh watermark at its 1:1 basis.                                                                                                                                                                                                                                            |
| **L-01** | The bridge-settlement window understated NAV (in-transit funds not counted by `hc + evm - pending`)                                    | Fixed in the fulfiller: a per-vault hold (`NAV_BRIDGE_HOLD_MS`, default 12 s) is armed after every bridge dispatch in either direction (deposit fulfillment's EVM→Core leg, withdrawal's Core→EVM `bridgeFromCore`); `stabilizeNav` refuses to produce a NAV until the window passes. Same-vault deposit batches already settle in one transaction, so no intra-batch window exists. |
| **L-02** | The HIP-3 transfer path hardcodes USDC for non-USDC-collateral DEXes                                                                   | Owner-managed `enabledHip3Dex` whitelist (the review's recommendation: an allowlist of USDC-collateral DEXes). Funding (`sendAssetToHip3`) is default-deny; withdrawal back to spot stays open for any non-reserved index so parked capital can never be stranded behind a disabled route. Index 0 and the spot sentinel are rejected in both directions.                            |
| **L-03** | `publishNav` rejected 0 → after a total loss `totalAssets()` / `pricePerShare()` misreported forever                                   | The contract now accepts a zero NAV as a valid total-loss report. The fulfiller publishes zero once on the transition (cached NAV > 0) and detects old-generation vaults that still revert on it. Deposits and withdrawal locks keep their own `nav > 0` guards.                                                                                                                     |
| **L-05** | Enabling the performance fee charged it retroactively on all gains accrued during the zero-fee period                                  | `setPerformanceFeeBps` checkpoints the HWM to the current net NAV per share on the 0→positive transition (never lowering an existing watermark), and bumps `interactionNonce` on any rate change so in-flight NAV snapshots priced under the old rate cannot land.                                                                                                                   |

## Not fixed — 3 of 12, all deliberate

### M-01 — Zero-supply bootstrap captures pre-existing vault assets → rejected as unrealistic

The 1 USDC creation seed is consumed by HyperCore account activation and never enters NAV — what remains capturable is 0.000001 USDC. The review's proof of concept (1,000,000 USDC of NAV at zero supply) cannot occur in our flow: a vault only reaches zero supply fresh (no NAV) or after a full wind-down in which every obligation has been paid out. The residual re-bootstrap edge case is under operational control.

### M-07 — Share-price inflation via 1 wei supply + donation → deferred

The outcome of the described attack is a deposit DoS (subsequent deposits mint 0 shares and revert), not theft. `minDepositUsdc` (owner-settable floor, ≥ 1 USDC) heavily limits practicality, and the code cited in the report (`sharesToUser = 1_000_000` dead-shares bootstrap) does not exist in this repository. Possible future hardening: a minimum-supply floor on withdrawals, while keeping a full wind-down (supply → 0) legal.

### L-04 — Named HyperCore agents stay authorized after rotation → acknowledged, mitigated off-chain

Revocation exists in the fulfiller service: every named registration carries a `valid_until` suffix (max 180 days; HyperCore auto-prunes expired slots), and a periodic sweep evicts stale named slots by overwriting them with a short-lived burner address. Only the fulfiller (`FULFILLER_ROLE`) can create named agents, so the authorization set is bounded and self-expiring. The review's recommendation (a single fixed agent name) would break the deliberate two-slot design: the fulfiller's own liquidation agent (`HL_AGENT_NAME`) and the leader-agent resurrection sweep (`LEADER_AGENT_NAME`) must live in separate HyperCore name slots. The on-chain `currentNamedAgent` field is a last-writer-wins cache and is intentionally not treated as an authorization record.

## What this does and doesn't tell you

A review narrows the space of bugs; it does not prove their absence. The protocol's remaining trust assumptions — the fulfiller's valuations, the admin keys, and the underlying platform — are design choices, not review findings, and are laid out honestly in [Security & Trust](/protocol-deep-dive/security-and-trust.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.buoy.finance/protocol-deep-dive/security-review-remediation.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
