BlendedVault v1.0.7 · Base Mainnet
Scope. v1.0.7 is a maintenance release — no changes to the smart contracts.
The vault runs the same audited, Sourcify-verified bytecode as v1.0.4 (exact_match).
One governance write: the deposit queue was reordered to the allocator's risk-adjusted
ranking, and the allocator now keeps it in sync every tick. Static-analysis reviewed (APPROVE),
fork-tested on a Base fork (5/5).
| Change | What it does |
|---|---|
| Allocator — measured withdrawals (E-04) | The deposit leg is sized against the amount the withdrawal leg actually delivered (read from the Rebalanced receipt), not the amount requested. A strategy that under-delivers no longer strands capital or reverts the deposit. |
| Allocator — missing APY ≠ 0% (A13-01) | A strategy the Morpho API failed to price is omitted from ranking (its position is preserved) instead of being quoted as 0% yield and withdrawn. |
| Allocator — queue deferral | Strategies clamped by tier caps are deferred to the tail of the deposit queue rather than holding a queue slot they cannot fund. |
| Swap form — share floor (B-06) | The swap form waits for the share preview before signing; it can no longer submit a deposit with minShares=0 while the quote is still loading. A rejected approval no longer fires the deposit either. |
| Indexer | /api/allocations now reports unreadable strategies instead of dropping them silently; proof uploads pin their file extension to the allowlisted type with nosniff/CSP headers. |
| Scripts | Daily-report metrics (rebalances, harvests, TVL fallback) now read live data instead of structurally zero; harvest.sh fee parsing fixed. |
| SEO & docs | Per-route canonicals, llms.txt, GA4, IndexNow, Search Console, one-command web deploy, REFERALS.md, and a full-stack audit pass. |
| Change | What it does |
|---|---|
| Allocator feature | The allocator now rewrites the vault's deposit queue to its risk-adjusted ranking every tick. New deposits land in the top-paying strategy in the deposit transaction itself — previously the queue was frozen at bootstrap tier order, so deposits parked in Prime (4.12%) while 99.5% of TVL sat in Frontier (5.93%). |
| Governance write | One onchain setDepositQueue (tx 0x8d97db…2bf, 75,271 gas):
[Frontier, HY, Prime, Moonwell, Steakhouse] = model ranking. |
| Fix 1 (automated review) | desiredDepositQueue returned registration order when ALL
strategies were frozen/unpriced — a market-wide freeze would have reverted
deposit routing to bootstrap order (Prime first). Now proposes no queue;
the last good order stays in force. |
| Fix 2 (automated review) | Queue sync moved BEFORE the rebalance legs so a repeating
TierLimitExceeded can't silently disable deposit routing. |
| Fork-tested | DepositQueueFork.t.sol (5/5 pass against the live vault on a
Base fork): deposit reaches the queue head in the same tx, reordering
reroutes instantly, duplicates/unregistered entries revert
InvalidQueueStrategy. Review verdict: APPROVE. |
| Test counts | Contracts 233 (CI) + 5 fork · Allocator 129 (up from 74) · Indexer 130 · 492 total (497 with fork). |
Users deposit USDC and receive shares. The vault allocates idle liquidity across a curated allowlist of ERC-4626 strategy vaults (MetaMorpho markets), subject to per-strategy caps and per-tier exposure limits. Five strategies are currently registered, spread across all three risk tiers.
Every state-changing entrypoint is guarded by ReentrancyGuardTransient
using EIP-1153 transient storage (Cancun). External strategy calls sit inside the
guard. Tests assert the re-entrant call failed, not just that something reverted.
_decimalsOffset() = 6 gives 1,000,000 virtual shares against 1 virtual
asset. A donation/first-depositor attack must burn ~1,000,000× what it can steal.
Fuzz-tested: the attacker cannot profit and the victim keeps ≥99.9% of principal.
Withdraw and redeem settle fees before pricing shares, so a holder cannot
exit ahead of harvest() and dodge their share of performance fees.
The high-water mark records the post-dilution price, preventing double-charging.
Deposits and withdrawals use the asset balance delta rather than trusting a strategy to move exactly the requested amount. Unconsumed approvals are revoked immediately. A lossy strategy cannot corrupt vault accounting.
MAX_STRATEGIES = 16 caps every accounting pass. Scheduled changes expire
after 30 days so a forgotten or pre-planted change cannot execute months later.
MAX_FEE_BPS = 2,000 (20%) is a hard, non-governable ceiling.
| Check | Status | Detail |
|---|---|---|
| Role separation in code | ✓ | 4 distinct roles: Admin, Curator, Allocator, Guardian |
| Two-step admin transfer | ✓ | beginAdminTransfer → acceptAdminTransfer |
| Admin grant/revoke blocked | ✓ | Only via two-step path; direct grantRole reverts |
| Timelock for risk-increasing changes | ✓ | New strategies, cap increases, parameter changes |
| Scheduled-change expiry | ✓ | 30-day grace period after becoming executable |
| Risk-reducing changes | ✓ | Immediate: lower caps, pause, increase cooldowns |
| Requirement | Status | Notes |
|---|---|---|
asset, totalAssets, convertToX, previewX |
✓ | previewX asserted equal to actual in fuzz tests |
maxDeposit / maxMint |
✓ | Returns 0 when paused |
maxWithdraw / maxRedeem |
✓ | Capped at reachable liquidity, and fee-aware as of v1.0.3 (D-01) |
| Rounding direction | ✓ | Always favours the vault; fuzz-tested round-trip never profits |
| First-deposit attack | ✓ | 1e6 virtual shares + minInitialDeposit |
mint mints exactly shares |
✓ | Tested |
| Slippage protection | ✓ | deposit(…, minShares), redeem(…, minAssets) |
8 invariants exercised across 819,200 calls (1,024 runs × 100 depth):
| Invariant | Asserts |
|---|---|
totalAssetsEqualsIdlePlusStrategies |
Accounting identity holds exactly |
totalAssetsCoversIdle |
No assets conjured from idle cash |
shareSupplyIsFullyAttributed |
Every share belongs to a known holder |
solvency |
All holders redeeming at once cannot exceed totalAssets |
strategyListIndexIntegrity |
listIndex stays in sync with strategyList |
liquidityWithinTotalAssets |
Never advertise more liquidity than owned |
queuesOnlyContainRegisteredStrategies |
No stale queue entries |
emptyVaultPricesAtPar |
HWM resets when fully drained |
| Package | Version | Notes |
|---|---|---|
| OpenZeppelin Contracts | 5.5.0 |
Industry standard, audited |
| Solidity | 0.8.28 |
evm_version = cancun for EIP-1153 |
| Node.js | 26.5.0 |
Runtime |
| viem | 2.55.0 |
TypeScript Ethereum client |
| Next.js | 16.2.12 |
Web frontend |