← All Reports

Royco Dawn (srRoyUSDC)

3.8
srRoyUSDC (Senior Royco USDC) / Ethereum Mainnet / March 26, 2026
View full report on GitHub →

Score Breakdown

CategoryWeightScore
Audits & Historical20%3.00
Centralization & Control30%3.50
Funds Management30%5.00
Liquidity Risk15%3.50
Operational Risk5%2.50
Final Score3.8 / 5.0
20%30%30%15%
Elevated Risk

Overview

srRoyUSDC is the Senior Vault token of Royco Dawn, an onchain yield-splitting protocol that divides yield into two tranches: Senior (conservative, protected) and Junior (enhanced returns, first-loss). Users deposit USDC into the Dawn Senior Vault (DSV) and receive srRoyUSDC tokens (ERC-4626) representing diversified Senior tranche exposure across multiple whitelisted yield markets.

The Senior Vault is curator-managed by the Royco Foundation, which allocates deposited USDC across whitelisted markets including autoUSD (Auto), savUSD (Avant), sNUSD (Neutrl), Aave v3 Core USDC, and stcUSD (Cap Finance, currently paused). Junior capital in each market absorbs losses first, providing a coverage buffer for Senior depositors.

Royco's tranche mechanics are enforced onchain, but the vault's capital path is trust-based: MultisigStrategy hands full custody of allocated funds to the treasury multisig.

  • Current PPS: ~1.005571 USDC per srRoyUSDC (verified onchain March 25, 2026)
  • Total Supply: ~10,673,575 srRoyUSDC
  • Total Assets: ~$10,733,046 USDC (100% deployed via MultisigStrategy, $0 held directly in vault)
  • Total Holders: ~8 (3 with meaningful holdings; 1 EOA holds ~69% of supply)
  • DeFiLlama TVL (Royco V2, all chains): ~$5.16M (Ethereum: $5.15M, Avalanche: $3.5K)
  • Management Fee: 0%
  • Performance Fee: 0% at vault level (performanceFee() returns 0, recipient is address(0)). Fees are charged at the Dawn market layer instead: 10% on ST yield, 0% on JT yield, 45% on yield share — verified via accountant getState(). Documentation claims "10% Senior / 20% Junior" are partially outdated (JT fee is 0%, yield share fee is undocumented).
  • Contract Created: January 6, 2026 (~78 days ago)

Links:

Risk Summary

Key Strengths

  1. Tranching mechanism provides structural protection (verified onchain at market level) — Junior capital absorbs losses first, enforced by onchain kernel/accountant contracts. Coverage verified: ~12.4% (Neutrl), ~12.5% (Tokemak) vs 10% required. Treasury holdings now evidence live exposure across Aave, two sNUSD senior tranche positions, autoUSD, and Avalanche savUSD. The srRoyUSDC vault itself still doesn't directly reference these contracts (indirect link via Treasury multisig).
  2. Institutional-grade access controls — KYC and whitelisting convert potential exploits into recoverable, legally actionable incidents
  3. Experienced founder — Jai Bhavnani has prior DeFi experience (Rari Capital, Ambo) and backing from reputable investors (Electric Capital, Coinbase Ventures, Hashed)
  4. Active bug bounty — $250K on Immunefi
  5. Conservative allocation framework — Concentration limits (40% per protocol/asset/chain), with Aave v3 USDC as a 20% liquidity reserve
  6. Dual-control vault upgrades — Vault implementation upgrades require Concrete team (ConcreteFactory owner, separate 3/5 multisig) cooperation, not just Royco team. RoycoFactory uses OZ AccessManager with 5-day minSetback and 1-day execution delay for upgrader role.
  7. Improved DEX liquidity — Curve pool grew from ~$600 to ~$490K since launch

Key Risks

  1. Still a new protocol — ~78 days in production (created January 6, 2026). Limited track record.
  2. Extreme holder concentration — One EOA holds ~69% of supply. ~$10.73M total assets with only ~8 holders.
  3. MultisigStrategy upgradeable without timelock — The Owner multisig (3/5) can upgrade the MultisigStrategy proxy immediately. This controls how all funds are deployed.
  4. Reliance on newer underlying protocols — 70% target allocation to Avant (savUSD) and Neutrl (sNUSD), which are relatively unknown protocols with limited public track records.
  5. 100% of assets admin-reported — Funds are deployed onchain to underlying protocols, but the vault cannot read those balances. The entire ~$10.73M totalAssets is reported via MultisigStrategy's adjustTotalAssets() (signed USDC delta per call). No oracle or onchain verification of actual positions. Emergency function unpauseAndAdjustTotalAssets() can bypass diff constraints, but requires the contract to be paused first (observable onchain).

Critical Risks

  • MultisigStrategy upgradeable with no timelock: The Owner multisig (3/5) controls the MultisigStrategy's ProxyAdmin and can upgrade the strategy implementation immediately. A malicious upgrade could redirect funds or bypass the 0.5% accounting constraint. This is the most direct risk vector.
  • Treasury multisig can divert 100% of allocated funds: onlyVault restricts who can call strategy entrypoints, but does not constrain what happens after allocation. Once the vault allocates, _allocateToPosition() transfers the full amount to the Treasury multisig. The strategy cannot force deployment into Aave / Dawn markets, and _retrieveAssetsFromMultisig() requires the multisig to approve funds back. This means the Treasury multisig has full practical control over all forwarded capital and can break the expected flow, divert funds elsewhere, or refuse to return them to the vault.
  • Underlying protocol risk is opaque: The quality and health of Avant, Neutrl, Auto, and Cap Finance positions are not easily verifiable. These protocols themselves are newer with limited audit and track record history.
  • Junior coverage is onchain but indirect from the vault: The Royco Dawn kernel/accountant contracts enforce Junior-first loss coverage onchain (verified: ~12.4-12.5% actual coverage, 10% required, 0 impermanent loss). However, the srRoyUSDC Concrete vault has no direct onchain link to these contracts — the Treasury multisig bridges this gap by holding Senior Tranche tokens and reporting values via adjustTotalAssets(). The loss waterfall enforcement is real at the market level, but the vault cannot independently verify it. Coverage buffer is thin (~2.5% above minimum) and Junior capital comes from only 2-3 depositor addresses per market.
  • Strategy totalAssets is manually reported, not derived from onchain data: totalAllocatedValue() returns a stored vaultDepositedAmount variable updated via adjustTotalAssets() by the treasury multisig. It does not read balances from Aave, Avant, Neutrl, or any underlying protocol. The reported value may not represent actual onchain positions — there is no mechanism to verify accuracy.

Full Report

Contract Addresses

Contract Address
srRoyUSDC (VaultProxy, ERC-4626) 0xcD9f5907F92818bC06c9Ad70217f089E190d2a32
Implementation (ConcreteAsyncVaultImpl) 0x1b5cd91e61505d431d2a61192a1006146bd9bb28
Owner (Gnosis Safe 3/5) 0x85de42e5697d16b853ea24259c42290dace35190
VAULT_MANAGER (Gnosis Safe 3/4) 0x7c405bbD131e42af506d14e752f2e59B19D49997
Multisig Safe (Treasury, 3/5) 0x170ff06326eBb64BF609a848Fc143143994AF6c8
Multisig Strategy (TransparentUpgradeableProxy) 0xd3F8Edff57570c4F9B11CC95eA65117e2D7A6C2D
MultisigStrategy Implementation 0xb417a7c43a7a8aa27bba2b2bb4639878532f9d0c
RoycoVaultMakinaStrategy 0xc5FeF644d59415cec65049e0653CA10eD9Cba778
ConcreteFactory (Vault Proxy Admin) 0x0265d73a8e61f698d8eb0dfeb91ddce55516844c
ConcreteFactory Owner (Gnosis Safe 3/5) 0xdc29BD10CB9000dffBb5aAcD30606c66f07c866C
RoycoFactory (AccessManager) 0xD567cCbb336Eb71eC2537057E2bCF6DB840bB71d
AdaptiveCurveYDM (Yield Distribution Model) 0x071B0FA065774b403B8dae0aE93A09Df5DE3DFAc
RoycoFactory Proxy (Dawn Market Factory) 0x7cC6fB28eC7b5e7afC3cB3986141797ffc27253C
Contract Creator 0xe86055afa2714dcd416594bc2db9b8fa69d70a47

Royco Dawn Market Contracts (On-Chain Tranching)

The Treasury multisig (0x170ff06326eBb64BF609a848Fc143143994AF6c8) holds Senior Tranche tokens in each market, linking the srRoyUSDC vault to the Royco Dawn tranching system. All contracts are verified on Etherscan.

Blueprint's own architecture docs describe MultisigStrategy as a design that "simply forwards deposits to a multi-sig wallet and retrieves" them later: Architecture.md#3.1.3 Multisig Strategies.

The configured multiSig address was also verified live onchain to be a standard Safe v1.4.1, not a custom treasury contract: MultisigStrategy.getMultiSig() returns 0x170ff06326eBb64BF609a848Fc143143994AF6c8, and that address responds to VERSION() = 1.4.1, getThreshold() = 3, and getOwners() = 5 owners.

Market Contract Address
Neutrl sNUSD Kernel 0x0aE0978B868804929fd4C06B3B22D9197B8cd3c6
Neutrl sNUSD Senior Tranche (ROY-ST-sNUSD) 0x2070Af1C865f5d764F673Baf5654822947e71243
Neutrl sNUSD Junior Tranche (ROY-JT-sNUSD) 0x3821eBea3BBbE23F3dea74f24082BD0f0b67f6c5
Neutrl sNUSD Accountant 0xCaa3F221fCf3c2EC7b6a49B73BB810cca35e1085
Neutrl sNUSD (legacy active market) Kernel 0xbdf2d357464727ee136a5f81479554f86759993a
Neutrl sNUSD (legacy active market) Senior Tranche (ROY-ST-sNUSD) 0x3b2df77f0eaa0ca98aaabffa96b03eaf08ec6c8e
Neutrl sNUSD (legacy active market) Junior Tranche (ROY-JT-sNUSD) 0x58c578d7e4f291ee1a11399d03e4418443e7a134
Neutrl sNUSD (legacy active market) Accountant 0x3371871e8901899fec4539ae2d1737d84acb6d89
Tokemak autoUSD Kernel 0x8748D1c21CC550B435487F473d9Aaf6C84dA46A6
Tokemak autoUSD Senior Tranche (ROY-ST-autoUSD) 0x73C641fe41EB0270C7f473f3c3E4A40eb97fd8dE
Tokemak autoUSD Junior Tranche (ROY-JT-autoUSD) 0x6f0D6567099621deE3850C673d73c532071A888d
Tokemak autoUSD Accountant 0xB0166629D78E3876F570f18B154A60b99024b6f4
Avant savUSD (Avalanche) Kernel 0x7240FF91b471217FF93349184ABE9f102Ca1955C
Avant savUSD (Avalanche) Senior Tranche (ROY-ST-savUSD) 0xDA7bf1788aecb94fE6D5D3f739358De94f43E5C9
Avant savUSD (Avalanche) Junior Tranche (ROY-JT-savUSD) 0x2dfde7811567562aaB39D0A292e43aa7195f6Cf6
Avant savUSD (Avalanche) Accountant 0x1067405d143a3973Dc48fD0Ea14ed6c1AF20dbb1

On-Chain Coverage Data (Verified March 26, 2026)

Each market's Accountant contract exposes getState() which returns all NAV and coverage parameters. Junior capital absorbs losses first, enforced by the kernel/accountant contracts (source code).

Market ST Effective NAV JT Effective NAV Coverage (JT/ST) Required Coverage Market State
Neutrl sNUSD ~1,172,599 sNUSD ~145,187 sNUSD 12.4% 10% PERPETUAL
Tokemak autoUSD ~1,168,619 autoUSD ~145,849 autoUSD 12.5% 10% PERPETUAL

Smokehouse USDC and Maple syrupUSDC markets have dust-level Senior NAV (<$10) and are not currently allocated by the Treasury. They contain only Junior capital (~$20K and ~$19.6K respectively).

  • Treasury multisig holds: ~1,172,390 ROY-ST-sNUSD shares at 0x2070Af1C865f5d764F673Baf5654822947e71243, ~1,981,280 ROY-ST-sNUSD shares at 0x3b2df77f0eaa0ca98aaabffa96b03eaf08ec6c8e, ~1,168,613 ROY-ST-autoUSD shares at 0x73C641fe41EB0270C7f473f3c3E4A40eb97fd8dE, and on Avalanche ~4,278,073 ROY-ST-savUSD shares at 0xDA7bf1788aecb94fE6D5D3f739358De94f43E5C9
  • Junior depositors: 2-3 independent addresses per market (e.g., 0x2d745a6596d47a0fe28a7db7bd9dc7bdbca4e476, 0xfef0bb8df6210e441f03de23edafb0150129e176)
  • No impermanent loss recorded in any market (both stImpermanentLoss and jtImpermanentLoss are 0)
  • Beta = 1.0 (1e18) in all markets — Junior uses the same underlying asset as Senior, meaning JT losses correlate with ST losses
  • Per-market Fixed-Term (Protection Mode) configuration differs significantly:
    • Neutrl sNUSD: fixedTermDuration = 0 — this market is permanently PERPETUAL and can never enter Protection Mode. When JT covers ST losses, jtImpermanentLoss is immediately erased — JT permanently absorbs the loss with zero recovery period. ST withdrawals are never paused. Liquidation threshold: ~100.09%.
    • Tokemak autoUSD: fixedTermDuration = 172,800s (2 days) — enters Protection Mode when JT covers losses. ST withdrawals blocked for up to 2 days. If no recovery, JT absorbs permanently. Liquidation threshold: 122.5%.
  • Dawn-level protocol fees (per-market, separate from vault fees):
    • ST protocol fee: 10% of Senior yield
    • JT protocol fee: 0%
    • Yield share protocol fee: 45% of the risk premium (yield share) paid from ST to JT
    • Fee recipient: 0x05ea95aE815809D77153Ed3500Ad6d936712b639
    • No fees taken during Fixed-Term state
  • JT withdrawal is coverage-constrained: The kernel enforces postOpSyncTrancheAccountingAndEnforceCoverage on every JT redemption — if the withdrawal would push utilization above 1.0 (coverage below required %), the tx reverts. JT can only withdraw the surplus above the coverage requirement. Current withdrawable surplus: ~28K sNUSD (Neutrl), ~28K autoUSD (Tokemak). However, coverage can still breach the threshold via underlying asset depreciation (no withdrawal needed) — this is when the loss escalation flow kicks in.

Audits and Due Diligence Disclosures

Royco Dawn has been audited by Hexens, with a Cantina competitive audit still in judging phase (262 submissions, judging by Royco team). The protocol is built on the Concrete vault framework (ConcreteAsyncVaultImpl) which was separately audited by Halborn, Code4rena, and Zellic according to the Concrete project. However, those audits cover the Concrete framework, not Royco Dawn-specific logic.

Auditor Scope Date Status Report
Hexens Royco Dawn (full audit) ~Jan 2026 Completed Report (PDF)
Hexens Royco Dawn (whitelist) ~Jan 2026 Completed Report (PDF)
Cantina Royco Dawn (competition) Jan 20-27, 2026 Judging (262 submissions, judged by Royco team) Competition Page
Cantina Royco Dawn (whitelist) Jan 2026 Completed Report (PDF)
Spearbit Royco V1 (not Dawn) Oct 2024 Completed Report (PDF)
Nethermind Royco Boosts (not Dawn) May 2025 Completed Blog Post

Smart Contract Complexity: Moderate — Upgradeable proxy (ERC-1967), ERC-4626 vault based on Concrete framework, MultisigStrategy for fund deployment, RoycoVaultMakinaStrategy (inactive), yield distribution model (AdaptiveCurveYDM), multi-market allocation, tranching mechanics with Protection Mode, OZ AccessManager for factory roles.

Note: The Cantina competition explicitly excluded from scope: oracle/NAV/share price manipulation, whitelisted parties behaving maliciously, external protocol bugs, centralization risks, MEV, and frontrunning. These exclusions mean some significant risk vectors remain unaudited.

Bug Bounty

Safe Harbor

Royco is not listed on the SEAL Safe Harbor Registry.

Historical Track Record

  • Royco V1 Launch: 2024 (incentive marketplace for DeFi liquidity)
  • Royco Dawn (V2) Launch: January 6, 2026 (~78 days in production)
  • Smart Contract Exploits: None known. Protocol is still very new.
  • Security Incidents: None found in rekt.news, de.fi REKT Database, or other exploit trackers.
  • TVL: ~$5.16M across Royco V2 on DeFiLlama (Ethereum: $5.15M, Avalanche: $3.5K). srRoyUSDC vault totalAssets(): ~$10.73M (discrepancy likely due to DeFiLlama methodology vs onchain reported value via MultisigStrategy).
  • Holder Distribution: ~8 holders with non-zero balances (3 with meaningful holdings). One EOA holds ~7.36M srRoyUSDC (~69% of supply). Morpho Blue holds ~2.83M (~26%, collateral from Morpho lending). Curve pool holds ~489K (~4.6%). Extreme concentration risk. The vault holds $0 USDC directly — 100% of ~$10.73M is deployed via MultisigStrategy.
  • Peg Stability: srRoyUSDC is a yield-bearing vault token priced at ~1.005571 USDC (reflecting accrued yield since January 6). The Curve CurveStableSwapNG pool (0x8fc753f96752b35f64d1bae514e6cf8db0b9322e) holds ~489K srRoyUSDC, a significant improvement from initial launch (~$600).
  • GitHub Activity: 548 commits on main branch, 2 contributors (Shivaansh Kapoor and Ankur Dubey). v1.0.0 released February 5, 2026. Repository has 4 stars.

Funds Management

The Senior Vault allocates deposited USDC across whitelisted markets where Junior tranche capital provides first-loss protection. The Royco Foundation curates allocations.

Target Allocations

Market Protocol Chain Target Actual (March 27, 2026) Status
savUSD Avant Avalanche 35% ~40% (~$4.278M) Active — at concentration cap
sNUSD Neutrl Ethereum 35% ~29.4% (~$3.153M, across 2 markets) Active — under target
Aave v3 Core USDC Aave Ethereum 20% ~19.7% (~$2.108M) Active (liquidity reserve)
autoUSD Auto Ethereum 10% ~10.9% (~$1.169M) Active
stcUSD Cap Finance Ethereum Paused 0% Paused (compressed yields)
sUSDai USD.ai Arbitrum Pending 0% Pending integration

Actual allocations computed from Treasury multisig token balances (see Reserve Location Reconciliation). Target allocations are set offchain by the Royco Foundation curator — not stored in any contract.

Concentration Controls:

  • Per-protocol: 40% max — Avant is currently at the cap (~40%)
  • Per-asset: 40% max
  • Per-chain: 40% max (Ethereum exempt) — Avalanche at ~40% (Avant savUSD only)
  • Aave v3 USDC exempt from per-market caps

Accessibility

  • Deposits: KYC-gated. Participants undergo KYC verification and deposits restricted to whitelisted addresses. Not fully permissionless.
  • Withdrawals: Request triggers up to 14-day unlock period. Vault sources liquidity from underlying Senior tranches. After unlock period, funds become claimable.
  • Fees: 0% management fee, 0% performance fee at the vault level (managementFee() and performanceFee() both return 0 with address(0) recipients, verified onchain). Fees are charged at the Dawn market layer: 10% on ST yield (stProtocolFeeWAD), 0% on JT yield (jtProtocolFeeWAD), 45% on yield share / risk premium (yieldShareProtocolFeeWAD) — verified via accountant getState(). Documentation claims "10% Senior / 20% Junior" are partially outdated. Vault-level fee updates require VAULT_MANAGER role (3/4 multisig).
  • Secondary Market: Improved since launch. Curve CurveStableSwapNG pool holds ~489K srRoyUSDC. Morpho Blue markets: srRoyUSDC/USDC (~$272K supply, 84% utilized), srRoyUSDC/pmUSD (~$1.99M supply, 91% utilized — loan asset is pmUSD, not direct USDC exit).

Collateralization

  • USDC deposits are deployed to underlying yield markets (not held as idle collateral)

  • Junior tranche capital in each market absorbs losses first — this is enforced onchain by each market's RoycoAccountant contract (verified in source code and on deployed contracts). The loss waterfall: JT effective NAV is reduced first; if JT is depleted, residual losses hit ST as stImpermanentLoss.

  • Onchain coverage verified (March 26, 2026): Neutrl sNUSD: 12.4% (required 10%), Tokemak autoUSD: 12.5% (required 10%). See On-Chain Coverage Data for full breakdown.

  • If losses exceed Junior coverage, Senior absorbs remaining losses

  • Loss Escalation Flow (enforced onchain by kernel/accountant):

    The flow differs per market depending on the fixedTermDuration parameter. Note: srRoyUSDC vault holders always face the 14-day async withdrawal queue at the Concrete vault layer regardless of market state below.

    Path A — Permanently PERPETUAL markets (fixedTermDuration = 0): Neutrl sNUSD (~29% of vault)

    1. Normal: ST and JT deposit/redeem instantly at market level (subject to coverage).
    2. Loss occurs: JT covers ST losses. jtImpermanentLoss is immediately erased — JT permanently absorbs the loss with zero recovery period. Market stays PERPETUAL. ST can always withdraw. No Protection Mode, no withdrawal pause, no recovery window for JT.
    3. Severe loss → Liquidation threshold (~100.09%): If utilization breaches the liquidation threshold, ST can exit with a self-liquidation bonus sourced from JT's remaining NAV. If JT is fully depleted, remaining losses hit ST as stImpermanentLoss.

    Path B — Fixed-Term markets (fixedTermDuration > 0): Tokemak autoUSD (~11% of vault, 2-day term)

    1. Normal (PERPETUAL): ST and JT deposit/redeem instantly at market level (subject to coverage).
    2. Small loss → Fixed-Term (Protection Mode): When JT covers ST drawdowns and jtImpermanentLoss exceeds dust tolerance, market transitions to Fixed-Term. ST withdrawals blocked (protects JT from ST withdrawing covered capital). JT deposits blocked (protects existing JT from dilution). ST deposits and JT redemptions remain enabled (JT can still exit surplus above coverage). YDM curve frozen. No protocol fees taken.
    3. Recovery within fixed term: Underlying asset recovers before the term expires, jtImpermanentLoss is repaid from ST appreciation, and the market returns to PERPETUAL.
    4. No recovery, term expires: jtImpermanentLoss is permanently zeroed — JT absorbs the loss forever with no recourse. Market returns to PERPETUAL. ST is made whole at JT's expense.
    5. Severe loss → Liquidation threshold (122.5%): The market is forced back to PERPETUAL regardless of Fixed-Term status. ST can withdraw with a self-liquidation bonus from JT's remaining NAV. If JT is fully depleted, remaining losses hit ST as stImpermanentLoss.

    Impact on srRoyUSDC: During Fixed-Term (Tokemak only, up to 2 days), the Treasury multisig cannot redeem Senior Tranche tokens from the affected market, blocking vault liquidity sourcing for that sleeve. Neutrl never blocks withdrawals. The srRoyUSDC vault itself is not aware of market states.

  • Coverage adjustments require 3-day notice to whitelisted depositors with incremental 1% daily changes

  • Loss propagation from Dawn markets to Senior vault is indirect: While the Royco Dawn kernel/accountant contracts enforce Junior-first loss coverage onchain, the srRoyUSDC Concrete vault itself cannot read these contracts. The Treasury multisig holds the Senior Tranche tokens and calls adjustTotalAssets() on the MultisigStrategy to report the net value. The loss waterfall (underlying drawdown → JT absorption → residual ST loss) is enforced at the market level, but the reporting of the net result to the vault is mediated by the multisig.

Collateral Concerns:

  • Underlying protocols (Avant, Neutrl, Auto, Cap Finance) are newer, less battle-tested DeFi protocols
  • savUSD (Avant) on Avalanche introduces cross-chain risk
  • sNUSD (Neutrl) and autoUSD (Auto) are relatively unknown protocols — limited public track record
  • Junior coverage is verifiable at the market level but indirect from the vault: Each market's Accountant exposes getState() returning JT effective NAV, coverage parameters, and impermanent loss. However, the srRoyUSDC Concrete vault has no onchain link to these contracts — it relies on the Treasury multisig holding Senior Tranche tokens and reporting values via adjustTotalAssets(). The tranching enforcement is onchain, but the vault's view of it is trust-based.
  • Junior capital is concentrated: Only 2-3 depositor addresses per market. Junior depositors could withdraw (subject to coverage enforcement — kernel blocks JT redemption if it would breach coverage).
  • Coverage buffer is thin: Active markets have 12.4-12.5% actual coverage vs 10% required — only ~2.5% buffer above minimum.
  • Beta = 1.0: In all markets, Junior uses the same underlying asset as Senior, meaning JT and ST losses are correlated. JT does not provide diversification — only a capital buffer.
  • Vault holds $0 USDC directly — 100% of ~$10.73M is deployed externally via MultisigStrategy. Importantly, this strategy is a full-custody handoff design: the vault calls allocateFunds(), the strategy's _allocateToPosition() forwards USDC directly to the Treasury multisig via safeTransfer(multiSig, amount), and assets return only if the multisig cooperates with _retrieveAssetsFromMultisig() / safeTransferFrom(multiSig, ...). There is no onchain guarantee that forwarded funds will be deployed to approved markets or returned to the vault. Once funds reach the Treasury multisig, that multisig can break the expected flow and use the funds freely.
  • Vault holds $0 USDC directly — 100% of ~$10.73M is deployed externally via MultisigStrategy. Importantly, this strategy is a full-custody handoff design: the vault calls allocateFunds(), the strategy's _allocateToPosition() forwards USDC directly to the Treasury multisig via safeTransfer(multiSig, amount), and assets return only if the multisig cooperates with _retrieveAssetsFromMultisig() / safeTransferFrom(multiSig, ...). There is no onchain guarantee that forwarded funds will be deployed to approved markets or returned to the vault. Once funds reach the Treasury multisig, that multisig can break the expected flow and use the funds freely.

Reserve Location Reconciliation (Verified March 27, 2026)

I traced the current reserve path further by combining live balanceOf() reads on Ethereum and Avalanche, Royco deployment configs, and treasury USDC transfer history.

Chain Position Contract Treasury Balance Approx. Raw Value
Ethereum Aave aUSDC 0x98c23e9d8f34fefb1b7bd6a91b7ff122f4e16f5c ~2,108,035.93 aUSDC ~$2.108M
Ethereum ROY-ST-sNUSD 0x2070Af1C865f5d764F673Baf5654822947e71243 ~1,172,390.32 shares ~$1.172M raw shares
Ethereum ROY-ST-sNUSD (legacy active market) 0x3b2df77f0eaa0ca98aaabffa96b03eaf08ec6c8e ~1,981,279.85 shares ~$1.981M raw shares
Ethereum ROY-ST-autoUSD 0x73C641fe41EB0270C7f473f3c3E4A40eb97fd8dE ~1,168,613.95 shares ~$1.169M raw shares
Avalanche ROY-ST-savUSD 0xDA7bf1788aecb94fE6D5D3f739358De94f43E5C9 ~4,278,072.87 shares ~$4.278M raw shares
  • These raw treasury balances sum to ~$10.708M, versus vault totalAssets() of ~$10.7378M. Residual unexplained gap: ~$29.4K.
  • The vault's second strategy is not at zero anymore: getStrategyData(0xc5FeF644d59415cec65049e0653CA10eD9Cba778) returns allocation 1,000 USDC on March 27, 2026.
  • The Treasury multisig sent ~3.155M USDC cumulatively to the Neutrl NUSD Router 0xa052883ebee7354fc2aa0f9c727e657fdeca744a, which aligns closely with the two live sNUSD senior tranche positions.
  • The Treasury multisig sent ~4.2628M USDC cumulatively to Circle TokenMinterV2 0xfd78ee919681417d192449715b2594ab58f5d002, and the same Treasury safe address on Avalanche currently holds ~4.2781M ROY-ST-savUSD shares in Royco's Avalanche kernel 0x7240FF91b471217FF93349184ABE9f102Ca1955C.
  • This is strong evidence for reserve location across Aave, Neutrl sNUSD, Tokemak autoUSD, and Avant savUSD.
  • Important caveat: if the tranche tokens are valued via current convertToAssets()/previewRedeem() outputs rather than raw share balances, the traced redeemable value is only ~$9.944M, about ~$794K below the vault's reported totalAssets(). So the reserve location is now mostly evidenced, but the vault's exact NAV methodology remains trust-based and cannot be treated as fully independently provable.

Provability

  • srRoyUSDC exchange rate is computed onchain via ERC-4626 (totalAssets() / totalSupply())
  • totalAssets() = totalAllocatedValue() from MultisigStrategy (~$10.73M). Vault holds $0 USDC directly — 100% of assets are reported by the strategy.
  • Accounting is admin-reported: The MultisigStrategy's totalAllocatedValue() is updated via adjustTotalAssets(int256 diff, uint256 nonce), called by the 3/5 treasury multisig (0x170ff06326eBb64BF609a848Fc143143994AF6c8). This is not computed from onchain positions — it is manually reported by the multisig.
  • How adjustTotalAssets works: The diff parameter is a signed raw USDC amount (not a percentage), added to or subtracted from vaultDepositedAmount. Positive diffs increase reported assets (yield accrual), negative diffs decrease them (loss reporting). The funds themselves are onchain in underlying protocols (Aave, Avant, etc.), but the vault cannot read those balances directly — instead the multisig manually reports the net change.
  • Accounting constraints (verified onchain March 25, 2026):
    • Max change per update: 50 bps (~0.5% of current vaultDepositedAmount), applies to both positive and negative diffs (abs(diff) is checked). At ~$10.73M, max ~$53.6K per call in either direction. If exceeded, contract auto-pauses without applying the diff — calls _pause() and returns immediately, discarding the change. This is a circuit breaker: the suspicious accounting update is rejected and the contract locks until STRATEGY_ADMIN calls unpauseAndAdjustTotalAssets().
    • Cooldown between updates: 43,200 seconds (12 hours). If violated, same circuit-breaker behavior — diff is discarded, contract pauses.
    • Validity period: 2,592,000 seconds (30 days) — if no update within 30 days, _previewPosition() reverts with AccountingValidityPeriodExpired, freezing deposits/withdrawals.
    • Sequential nonce required (current: 37, ~1 update every 2 days). Prevents replay/out-of-order submissions.
    • Underflow protection: negative diffs cannot reduce vaultDepositedAmount below zero (reverts with InsufficientUnderlyingBalance). This is a floor guard only — the 0.5% cap is the actual per-call limit on losses.
    • Last updated: March 25, 2026
  • Emergency bypass — unpauseAndAdjustTotalAssets(int256 diff): Callable only by STRATEGY_ADMIN. Skips diff validation (no nonce check, no percentage cap, no cooldown). The diff is int256 — can be positive or negative, unconstrained in magnitude. However, the contract must be paused first — OpenZeppelin's _unpause() reverts if not paused. This means the bypass can only be used after the circuit breaker has already triggered (a Paused event is emitted onchain when adjustTotalAssets fails validation). The intended flow: (1) adjustTotalAssets exceeds 0.5% cap or cooldown → contract auto-pauses, diff discarded, Paused event emitted; (2) STRATEGY_ADMIN investigates the anomaly; (3) STRATEGY_ADMIN calls unpauseAndAdjustTotalAssets(diff) → emits Unpaused + AdjustTotalAssets in one tx. This design ensures the emergency bypass is always preceded by an observable onchain pause event, providing a detection window before the unconstrained adjustment is applied.
  • Observed usage pattern: 36 adjustments since Jan 30, 2026. Overwhelmingly small positive diffs (+$800–4,000 USDC for yield accrual). One negative diff observed (nonce 7: -$1,225 USDC). Calls every 12–72 hours.
  • Yield distribution — AdaptiveCurveYDM (0x071B0FA065774b403B8dae0aE93A09Df5DE3DFAc): Determines what percentage of Senior yield is redirected to Junior as a risk premium. Inspired by Morpho's AdaptiveCurveIrm. Uses a piecewise linear curve with a kink at 90% utilization (Junior capital backing Senior exposure). When utilization > 90% (Junior scarce), Junior's yield share increases exponentially over time to attract more Junior capital; when < 90% (Junior abundant), it decreases. Immutable contract — no admin functions, no owner, no upgradeability. Parameters are set once at market initialization and the curve adapts autonomously. Floor: 0.01% JT yield share, ceiling: 100%.
  • Per-market Junior/Senior coverage is verifiable onchain: Each market's Accountant contract exposes getState() returning lastSTEffectiveNAV, lastJTEffectiveNAV, lastSTImpermanentLoss, lastJTImpermanentLoss, coverageWAD, betaWAD, and marketState. The kernel exposes getState() returning stOwnedYieldBearingAssets and jtOwnedYieldBearingAssets. These can be queried without protocol-specific tooling (standard eth_call to verified contracts).
  • Underlying market positions must be verified by checking each external protocol individually
  • No third-party verification mechanism (no Chainlink PoR, no custodian attestations)
  • Overall provability is limited but better than initially documented: Treasury holdings on Ethereum and Avalanche now evidence ~99.7% of reported assets by raw share balances, but the vault exchange rate still depends on the MultisigStrategy correctly reporting strategy NAV. The current tranche convertToAssets() outputs do not fully reconcile to the reported totalAssets(), so the exact accounting methodology remains trust-based.

Liquidity Risk

  • Primary Exit: Async withdrawal from vault (ERC-7540 pattern — maxWithdraw() returns 0, confirming no instant redemption). Request triggers up to 14-day unlock period. Vault sources liquidity from underlying Senior tranches during this window. The 20% Aave v3 USDC allocation is described as a "liquidity reserve" but this refers to the vault's internal rebalancing speed (Aave is instant to unwind on the vault side), not instant withdrawals for depositors — all exits go through the request-and-wait mechanism.
  • Secondary Exit (DEX): Curve CurveStableSwapNG pool (0x8fc753f96752b35f64d1bae514e6cf8db0b9322e) holds ~489K srRoyUSDC — significant improvement from ~$600 at initial assessment. Meaningful DEX liquidity now exists.
  • Morpho Blue Markets (verified via Morpho API, March 25, 2026):
    • srRoyUSDC/USDC (91.5% LLTV, market): ~$272K supply, ~$228K borrowed, 84% utilized — meaningful USDC exit path, significant growth from ~$22K at initial assessment
    • srRoyUSDC/pmUSD (86% LLTV, market): ~$1.99M supply, ~$1.81M borrowed, 91% utilized — largest market by supply, but loan asset is pmUSD (Precious Metals USD from RAAC protocol), not direct USDC exit. Morpho Blue holds ~2.83M srRoyUSDC (~26% of total supply) as collateral.
    • Two additional markets (srRoyUSDC/pmUSD at 91.5% LLTV and srRoyUSDC/USDC at 86% LLTV) are empty or negligible
  • Slippage Analysis: Curve pool now provides meaningful exit liquidity (~$490K). Large exits still face slippage given the vault's ~$10.7M total assets.
  • Withdrawal Queues: Up to 14-day max during normal conditions. Protection Mode impact on vault liquidity is per-market and proportional to exposure, not a vault-wide pause: Neutrl sNUSD (fixedTermDuration=0) never enters Protection Mode — ST can always withdraw. Tokemak autoUSD has a 2-day Protection Mode that blocks ST redemptions during losses. Only the affected market's allocation becomes illiquid; the vault can still source from other markets.
  • Stress Scenario: If Tokemak enters Protection Mode, ~$1.17M of vault exposure (~11%) becomes temporarily illiquid (up to 2 days). Neutrl never pauses. In a worst case where all non-Aave, non-Neutrl markets are impaired simultaneously, the vault could still source from Aave (~$2.1M, instant unwind) and Neutrl (~$3.15M, always redeemable). The Curve pool provides an additional escape valve for smaller positions.
  • Large Holder Impact: One EOA holds ~69% of supply (~7.36M srRoyUSDC). A withdrawal of this magnitude would require unwinding the vast majority of underlying positions.

Centralization & Control Risks

Governance

The vault governance involves multiple multisigs and two factory contracts with different access controls.

Owner Multisig (Vault Owner): 0x85de42e5697d16b853ea24259c42290dace35190

  • Type: Gnosis Safe v1.3.0
  • Threshold: 3 of 5 signers (anonymous EOAs, no ENS)
  • Powers: Vault owner (strategy management, parameters). Also holds ADMIN_UPGRADER_ROLE on RoycoFactory with 1-day execution delay. Controls MultisigStrategy proxy upgrades (no timelock).

VAULT_MANAGER Multisig: 0x7c405bbD131e42af506d14e752f2e59B19D49997

  • Type: Gnosis Safe
  • Threshold: 3 of 4 signers (3 signers overlap with Owner multisig, 1 new signer)
  • Powers: Can update fees (management/performance), toggle queue, manage withdrawal requests

Multisig Safe (Treasury): 0x170ff06326eBb64BF609a848Fc143143994AF6c8

  • Type: Gnosis Safe v1.3.0
  • Threshold: 3 of 5 signers (same 5 signers as Owner multisig — no separation of powers)
  • Powers: Controls adjustTotalAssets() on MultisigStrategy (admin-reported accounting)

ConcreteFactory Owner: 0xdc29BD10CB9000dffBb5aAcD30606c66f07c866C

  • Type: Gnosis Safe v1.3.0
  • Threshold: 3 of 5 signers (completely different signers from Royco — these are Concrete protocol team)
  • Powers: Approves and deploys vault implementation upgrades via ConcreteFactory

Signer Overlap: The Owner and Treasury multisigs share identical 5 signers. The VAULT_MANAGER shares 3 of those 5 plus 1 additional signer. Effectively, the same group of anonymous EOAs controls vault administration, treasury, and fee management. The ConcreteFactory owner is a separate party (Concrete team).

Timelock Architecture:

  • RoycoFactory (AccessManager): Uses OZ AccessManager with minSetback of 432,000 seconds (5 days) and expiration of 604,800 seconds (7 days). The Owner multisig has ADMIN_UPGRADER_ROLE with a 1-day (86,400s) execution delay for factory-mediated operations.
  • Vault implementation upgrades: Controlled by the ConcreteFactory (owned by Concrete team 3/5 multisig). The vault's upgrade() function requires msg.sender == factory (the ConcreteFactory). This means vault implementation upgrades require cooperation between the Concrete team and Royco team — a dual-control mechanism.
  • MultisigStrategy upgrades: Controlled by a ProxyAdmin owned by the Royco Owner multisig (3/5). No timelock — can be upgraded immediately. This is the most direct risk vector.
  • Accounting adjustments: No timelock, but constrained by max 0.5% change per update and 12-hour cooldown.
  • Dawn market setConversionRate: Each kernel's NAV conversion rate can be admin-set via setConversionRate() (AccessManager role, no timelock). For ERC4626 kernels, NAV = ERC4626.convertToAssets(shares) × conversionRate. Manipulating this rate directly affects raw NAVs, which drives the entire tranching/loss waterfall. Currently: Neutrl uses oracle (stored rate = 0), Tokemak uses hardcoded 1:1 (stored rate = 1e18).

Upgradeable Contracts:

  • srRoyUSDC vault: ERC-1967 proxy → ConcreteAsyncVaultImpl (upgradeable via ConcreteFactory, requires Concrete team approval)
  • MultisigStrategy: TransparentUpgradeableProxy → MultisigStrategy implementation (upgradeable by Owner multisig, no timelock)
  • RoycoVaultMakinaStrategy: New strategy added, currently has a small live allocation (~1,000 USDC on March 27, 2026)

Programmability

  • srRoyUSDC PPS is calculated onchain via ERC-4626 standard (totalAssets() / totalSupply())
  • Yield distribution uses the onchain AdaptiveCurveYDM model
  • Fund deployment and rebalancing are executed by the MultisigStrategy, which is controlled by the 3/5 treasury multisig — significant manual intervention
  • A second strategy (RoycoVaultMakinaStrategy) has been added and currently has a small live allocation (~1,000 USDC on March 27, 2026). It uses an OZ AccessManager authority rather than direct multisig control, potentially for automated fund deployment via Makina.
  • Market selection, allocation targets, and coverage parameters are set by the Royco Foundation (offchain decisions)
  • Fee management (management/performance fees) requires VAULT_MANAGER role (3/4 multisig). Both fees are currently 0%.
  • accrueYield() is callable by anyone (no access control) — triggers yield computation and fee share minting (currently mints 0 since fees are 0%)
  • Protection Mode activation and parameters are configurable
  • KYC gating for deposits adds an offchain dependency

External Dependencies

  1. Underlying Yield Protocols (Critical):

    • Avant (savUSD, Avalanche) — 35% target allocation. Newer protocol. Cross-chain dependency adds bridge risk.
    • Neutrl (sNUSD, Ethereum) — 35% target allocation. Newer protocol with limited public track record.
    • Aave v3 (Ethereum) — 20% target. Blue-chip protocol, lowest risk dependency.
    • Auto (autoUSD, Ethereum) — 10% target. Newer protocol.
    • Cap Finance (stcUSD, Ethereum) — Currently paused.
    • USD.ai (sUSDai, Arbitrum) — Pending integration. Cross-chain dependency.
  2. Concrete Framework (Medium-High): The vault implementation uses the Concrete vault framework (ConcreteAsyncVaultImpl). Bugs in Concrete would affect srRoyUSDC. Additionally, the ConcreteFactory (owned by the Concrete team's 3/5 multisig) serves as the vault's proxy admin and controls implementation upgrades. This adds a third-party trust dependency — the Concrete team can approve new vault implementations.

  3. Accounting/NAV (High): totalAllocatedValue() on the MultisigStrategy is manually adjusted by the 3/5 treasury multisig via adjustTotalAssets(). There is no oracle — deployed asset values are admin-reported. The vault holds $0 USDC directly — 100% of totalAssets() (~$10.73M) is reported via this mechanism. The Cantina competition excluded NAV/share price manipulation from scope, confirming this is a known trust assumption. Constraints exist (max 0.5% change per update, 12-hour cooldown, 30-day validity) but the system ultimately relies on the multisig reporting accurate values.

Operational Risk

  • Team: Jai Bhavnani (Co-founder & CEO of Waymont, the company behind Royco). Previously co-founded Rari Capital (grew to $1.5B AUM, sold to Tribe DAO for $375M). Also founded Ambo (acquired by MyCrypto). James Folkestad is co-founder. Team is small — only 2 contributors to the GitHub repo (Shivaansh Kapoor and Ankur Dubey).
  • Funding: Pre-seed completed. Investors include Electric Capital, Coinbase Ventures, Amber Group, and Hashed. Exact amount undisclosed.
  • Documentation: Adequate. Gitbook documentation covers mechanism, risk framework, key addresses, and DSV. Some areas lack depth (oracle mechanism, detailed per-market coverage data). No comprehensive technical documentation for smart contract integrations.
  • Legal: Waymont Co., based in Los Angeles, California. Founded 2022. Formal legal structure not disclosed in detail. KYC required for participation suggests regulatory compliance efforts.
  • Incident Response: Hypernative being configured for continuous monitoring. Emergency upgrade system in place. Private security council being assembled. No publicly documented incident response plan yet.
  • License: Not specified in contracts.

Monitoring

Key Contracts to Monitor

Contract Address Purpose Key Events/Functions
srRoyUSDC Vault 0xcD9f5907F92818bC06c9Ad70217f089E190d2a32 Vault state Deposit, Withdraw, Transfer, totalAssets(), totalSupply(), convertToAssets(), accrueYield()
Owner Multisig 0x85de42e5697d16b853ea24259c42290dace35190 Governance Submitted/confirmed/executed transactions, owner changes
VAULT_MANAGER 0x7c405bbD131e42af506d14e752f2e59B19D49997 Fee/queue mgmt Fee updates, queue toggles, signer changes
MultisigStrategy 0xd3F8Edff57570c4F9B11CC95eA65117e2D7A6C2D Fund deployment adjustTotalAssets(), strategy changes, proxy upgrades
RoycoVaultMakinaStrategy 0xc5FeF644d59415cec65049e0653CA10eD9Cba778 Secondary strategy allocateFunds(), totalAllocatedValue() (~1,000 USDC allocated on March 27, 2026)
Multisig Safe (Treasury) 0x170ff06326eBb64BF609a848Fc143143994AF6c8 Treasury/accounting adjustTotalAssets() calls, large transfers, signer changes
ConcreteFactory 0x0265d73a8e61f698d8eb0dfeb91ddce55516844c Vault proxy admin Implementation approvals, vault upgrades
RoycoFactory 0xD567cCbb336Eb71eC2537057E2bCF6DB840bB71d AccessManager Role grants, scheduled operations, market creation
AdaptiveCurveYDM 0x071B0FA065774b403B8dae0aE93A09Df5DE3DFAc Yield distribution Parameter changes
Neutrl sNUSD Kernel 0x0aE0978B868804929fd4C06B3B22D9197B8cd3c6 Dawn market (sNUSD) syncTrancheAccounting(), pause(), getState(), coverage changes
Tokemak autoUSD Kernel 0x8748D1c21CC550B435487F473d9Aaf6C84dA46A6 Dawn market (autoUSD) syncTrancheAccounting(), pause(), getState(), coverage changes
RoycoFactory Proxy 0x7cC6fB28eC7b5e7afC3cB3986141797ffc27253C Dawn market factory deployMarket(), role grants, scheduled operations

Critical Monitoring Points

  • PPS (Price Per Share): Track convertToAssets(1e6) — should be monotonically increasing. Alert on any decrease (indicates loss event or Protection Mode). Current: ~1.005571.
  • Total Assets: Monitor totalAssets() — currently 100% dependent on MultisigStrategy's admin-reported totalAllocatedValue(). Cross-reference with actual onchain positions in underlying protocols (Aave, Avant, Neutrl, Auto) for sanity checking.
  • Accounting Updates (adjustTotalAssets):
    • Track all adjustTotalAssets(int256 diff, uint256 nonce) calls on MultisigStrategy (0xd3F8Edff57570c4F9B11CC95eA65117e2D7A6C2D)
    • diff is a signed raw USDC amount (positive = yield accrual, negative = loss). Normal range: +$800–4,000 per update.
    • Alert on: negative diffs (loss events), unusually large positive diffs (>$10K), nonce gaps or out-of-sequence, updates faster than 12-hour cooldown
    • Alert on contract pause: if diff exceeds 0.5% cap or cooldown is violated, the contract auto-pauses instead of reverting
    • Critical alert on unpauseAndAdjustTotalAssets(): This emergency function skips diff validation (no cap, no cooldown, no nonce). Can only be called when the contract is already paused (circuit breaker triggered). Monitor for the sequence: Paused event (circuit breaker) followed by Unpaused + AdjustTotalAssets in same tx. Any such sequence is a high-severity event requiring immediate investigation.
    • Monitor accountingValidityPeriod: if no update for 30 days, vault freezes (deposits/withdrawals revert)
    • Verify nonce increments sequentially (current: 37)
  • Governance: Monitor Owner multisig for MultisigStrategy proxy upgrade transactions (no timelock). Monitor ConcreteFactory for vault implementation upgrade proposals. Monitor RoycoFactory for role grants and scheduled operations.
  • Fee Changes: Monitor VAULT_MANAGER multisig for updateManagementFee() and updatePerformanceFee() calls. Currently both 0% — any change would enable fee share minting via accrueYield().
  • Strategy: Monitor MultisigStrategy for fund movements. Monitor RoycoVaultMakinaStrategy for growth beyond its current small allocation (~1,000 USDC on March 27, 2026).
  • Protection Mode / Fixed-Term State: Alert on any market transitioning from PERPETUAL (0) to FIXED_TERM (1) state via marketState in accountant getState(). This means JT is covering ST losses and Senior withdrawals are paused.

Junior Vault / Tranching Monitoring

The Junior tranche provides the first-loss buffer protecting Senior depositors. Loss of Junior capital directly reduces srRoyUSDC's structural protection. All data below is queryable onchain via the kernel and accountant contracts.

Contracts to poll (via getState()):

Market Accountant Kernel Junior Tranche (ERC20)
Neutrl sNUSD 0xCaa3F221fCf3c2EC7b6a49B73BB810cca35e1085 0x0aE0978B868804929fd4C06B3B22D9197B8cd3c6 0x3821eBea3BBbE23F3dea74f24082BD0f0b67f6c5
Tokemak autoUSD 0xB0166629D78E3876F570f18B154A60b99024b6f4 0x8748D1c21CC550B435487F473d9Aaf6C84dA46A6 0x6f0D6567099621deE3850C673d73c532071A888d

Key metrics (from Accountant getState() tuple):

Field Index Type Alert Condition
lastMarketState 0 uint8 Alert if != 0 (0 = PERPETUAL, 1 = FIXED_TERM). Fixed-Term means JT is actively covering ST losses and Senior withdrawals are paused.
coverageWAD 3 uint64 Alert on any change. Currently 1e17 (10%) for both active markets. Decrease = less protection.
betaWAD 4 uint96 Alert on any change. Currently 1e18 (100%) — JT has same underlying exposure as ST.
lastSTRawNAV 10 uint256 Track for trend. Decrease = underlying asset depreciation.
lastJTRawNAV 11 uint256 Track for trend. Decrease = JT asset depreciation (since beta=1.0, correlates with ST).
lastSTEffectiveNAV 12 uint256 Alert if < lastSTRawNAV (means JT has NOT fully covered ST losses).
lastJTEffectiveNAV 13 uint256 Critical metric. Alert if drops >10% in 24h. Alert if approaches 0 (JT depleted = no protection).
lastSTImpermanentLoss 14 uint256 Alert if != 0. Non-zero means ST has suffered losses beyond what JT could cover.
lastJTImpermanentLoss 15 uint256 Alert if != 0. Non-zero means JT is actively covering ST losses.
fixedTermEndTimestamp 2 uint32 If market is in FIXED_TERM, this is when the protection period ends. After expiry, jtImpermanentLoss is zeroed (JT permanently absorbs loss).

Key metrics (from Kernel getState() tuple):

Field Index Type Alert Condition
stOwnedYieldBearingAssets 3 uint256 Track. Cross-reference with accountant NAV for consistency.
jtOwnedYieldBearingAssets 4 uint256 Track. Significant decrease = JT capital leaving.

Derived metrics to compute and track:

Metric Formula Baseline (March 26, 2026) Alert Threshold
Coverage ratio (Neutrl) lastJTEffectiveNAV / lastSTEffectiveNAV 12.4% < 11% (approaching 10% minimum)
Coverage ratio (Tokemak) lastJTEffectiveNAV / lastSTEffectiveNAV 12.5% < 11% (approaching 10% minimum)
Utilization (Neutrl) (stRawNAV + jtRawNAV × beta) × coverageWAD / jtEffectiveNAV ~90.8% > 95% (approaching liquidation at 100%)
Utilization (Tokemak) (stRawNAV + jtRawNAV × beta) × coverageWAD / jtEffectiveNAV ~90.0% > 95% (approaching liquidation at 122.5%)

Junior depositor monitoring:

Senior Tranche token monitoring (Treasury holdings):

Target allocations are set offchain by the Royco Foundation curator — there is no onchain registry of targets. Actual allocations must be reconstructed from the Treasury multisig's token balances across chains.

How to compute current allocation per market:

Step Chain Call Purpose
1 Ethereum balanceOf(0x170ff0...) on aUSDC 0x98c23e9d8f34fefb1b7bd6a91b7ff122f4e16f5c Aave USDC position
2 Ethereum balanceOf(0x170ff0...) on ROY-ST-sNUSD 0x2070Af1C865f5d764F673Baf5654822947e71243 Neutrl sNUSD market 1
3 Ethereum balanceOf(0x170ff0...) on ROY-ST-sNUSD 0x3b2df77f0eaa0ca98aaabffa96b03eaf08ec6c8e Neutrl sNUSD market 2
4 Ethereum balanceOf(0x170ff0...) on ROY-ST-autoUSD 0x73C641fe41EB0270C7f473f3c3E4A40eb97fd8dE Tokemak autoUSD market
5 Avalanche balanceOf(0x170ff0...) on ROY-ST-savUSD 0xDA7bf1788aecb94fE6D5D3f739358De94f43E5C9 Avant savUSD market
6 Convert each balance to USD via convertToAssets() on each tranche (for Senior Tranche shares) or 1:1 for aUSDC Get USD value per position
7 Sum all positions and compute % per market Current allocation

Alert conditions:

  • Any single protocol exceeding 40% concentration cap (Avant currently at ~40%)
  • Any single chain exceeding 40% (Avalanche currently at ~40%, Ethereum exempt)
  • Allocation drift >5% from last known target for any market
  • New positions appearing (Treasury holding new token types)
  • Positions disappearing (Treasury balance dropping to 0 on an existing market)

Important limitation: The vault's totalAssets() (~$10.74M) is reported by the MultisigStrategy via adjustTotalAssets(). The sum of Treasury token balances converted via convertToAssets() (~$9.944M) does not exactly match the vault's reported value — there is a ~$794K gap. This means allocation percentages computed from Treasury balances are approximate. The vault's own accounting is the authoritative source, but it doesn't break down by market. New market deployment monitoring:

Recommended polling frequency:

  • Accountant/Kernel getState(): Every 1 hour (coverage and market state)
  • Junior Tranche Transfer events: Real-time (event subscription) or every 15 minutes
  • Treasury Senior Tranche balanceOf(): Every 6 hours
  • Allocation monitoring: Daily — compute per-market allocation from Treasury balances, alert on concentration cap breaches or significant drift
  • RoycoFactory deployMarket() events: Daily
  • Holder Concentration: Monitor the dominant EOA holder (~69% of supply) and Morpho Blue (~26%) for significant movements.
  • Underlying Protocols: Monitor health of Avant (savUSD), Neutrl (sNUSD), Auto (autoUSD), and Aave.
  • Recommended Frequency: Hourly for PPS, governance, and strategy. Daily for underlying protocol health and allocation. Immediate alerts for proxy upgrades and fee changes.

Token Minting Analysis

Current Implementation — No Direct Minting Without Assets

The vault implementation (ConcreteAsyncVaultImpl) uses standard ERC-4626 minting:

  1. mint(uint256 shares, address receiver) — Standard ERC-4626. Internally calls SafeERC20.safeTransferFrom() to pull USDC from the caller before minting shares. Cannot mint without depositing USDC.

  2. deposit(uint256 assets, address receiver) — Standard ERC-4626 deposit. Same underlying flow — requires USDC transfer first.

  3. Fee Share Minting (accrueYield()) — The vault can mint shares to fee recipients via accrueManagementFee() and accruePerformanceFee(). These are the only code paths that mint shares without requiring a corresponding USDC deposit. However:

    • Both management fee and performance fee are currently 0% (verified onchain March 25, 2026)
    • Both fee recipient addresses are address(0) (no recipient set)
    • accrueYield() is publicly callable (no access control), but currently mints 0 shares since fees are 0%
    • Fee changes require the VAULT_MANAGER role (3/4 Gnosis Safe at 0x7c405bbD131e42af506d14e752f2e59B19D49997)
    • Fee caps exist: MAX_MANAGEMENT_FEE and MAX_PERFORMANCE_FEE (set in the implementation)

Indirect Inflation Vectors

While tokens cannot be directly minted without assets, the following mechanisms could effectively inflate or dilute value:

  1. adjustTotalAssets() — PPS Inflation (Constrained)

    • The treasury multisig (3/5) can call adjustTotalAssets(int256 diff, uint256 nonce) on the MultisigStrategy to inflate the reported totalAllocatedValue()
    • diff is a signed raw USDC amount added to vaultDepositedAmount. Positive values inflate totalAssets() and thus PPS.
    • Constrained: max 50 bps (~0.5%) per update, 12-hour cooldown, sequential nonce, 30-day validity period
    • At ~$10.73M total assets, each update can inflate by at most ~$53.6K
    • This doesn't mint new tokens but can gradually misrepresent value
    • Emergency bypass: unpauseAndAdjustTotalAssets(int256 diff) (STRATEGY_ADMIN only) skips caps/cooldowns — requires contract to be paused first (circuit breaker must have triggered), then enables unconstrained adjustment in a single call
  2. Fee Manipulation → Fee Share Minting

    • The VAULT_MANAGER (3/4 Safe) could set non-zero fees via updateManagementFee() / updatePerformanceFee()
    • Then accrueYield() (callable by anyone) would mint fee shares to the fee recipient
    • Combined with adjustTotalAssets() inflation: the multisig could inflate totalAssets (creating fake "yield"), then fee shares would be minted based on this fake yield
    • This is a realistic attack vector requiring cooperation of the VAULT_MANAGER (3/4 Safe) and Treasury (3/5 Safe) — which share overlapping signers
  3. MultisigStrategy Proxy Upgrade (No Timelock)

    • The Owner multisig (3/5) can upgrade the MultisigStrategy implementation immediately
    • A malicious implementation could remove the 0.5% cap on adjustTotalAssets(), enabling unlimited PPS inflation
    • Or could add a function that drains deposited USDC directly
  4. Vault Implementation Upgrade (Dual-Control)

    • A new vault implementation could include an unrestricted mint() function
    • Requires ConcreteFactory owner (Concrete team 3/5 multisig) to approve the new implementation
    • This is the highest-impact but hardest-to-execute vector — requires cooperation between two separate teams

Conclusion

In the current implementation, there is no function that can mint srRoyUSDC tokens without depositing underlying USDC. The mint function is standard ERC-4626 and requires USDC transfer. Fee minting is disabled (0% fees, no recipient set).

The most realistic risk vector is the MultisigStrategy proxy upgrade (no timelock, controlled by Owner 3/5 multisig), which could remove accounting constraints and enable PPS manipulation or fund diversion. The fee manipulation path (VAULT_MANAGER sets fees + treasury inflates totalAssets) is also viable but slower-acting due to the 0.5% cap and 12-hour cooldown on accounting adjustments.


Reassessment Triggers

  • Time-based: Reassess in 2 months (May 2026) or when Cantina audit judging concludes and remediation is publicly confirmed
  • TVL-based: Reassess if TVL exceeds $50M or drops below $2M
  • Incident-based: Reassess after any exploit, Protection Mode activation, or governance change
  • Governance-based: Reassess if timelock is added to MultisigStrategy, the multisig threshold/signers change, MultisigStrategy is replaced, or a new governance mechanism is introduced
  • Strategy-based: Reassess if RoycoVaultMakinaStrategy grows materially beyond its current small allocation (~1,000 USDC)
  • Fee-based: Reassess if performance or management fees are changed from 0%
  • Underlying protocol: Reassess if any whitelisted market (Avant, Neutrl, Auto) experiences an exploit or significant issue, or if the set of underlying protocols / markets changes materially

Appendix: Contract Architecture

┌─────────────────────────────────────────────────────────────────────┐
│                     CONCRETE VAULT LAYER                            │
│                                                                     │
│  ┌──────────────────────┐       ┌───────────────────────────────┐  │
│  │  srRoyUSDC Vault     │       │  MultisigStrategy             │  │
│  │  (ERC-4626 Proxy)    │──────▶│  (TransparentUpgradeableProxy)│  │
│  │  0xcD9f...           │       │  0xd3F8...                    │  │
│  │                      │       │                               │  │
│  │  totalAssets() reads │       │  adjustTotalAssets(diff,nonce) │  │
│  │  from strategy       │       │  unpauseAndAdjustTotalAssets() │  │
│  └──────────┬───────────┘       └──────────────┬────────────────┘  │
│             │                                  │                    │
│             │ upgrade                          │ calls              │
│             ▼                                  ▼                    │
│  ┌──────────────────────┐       ┌───────────────────────────────┐  │
│  │  ConcreteFactory     │       │  Treasury Multisig (3/5)      │  │
│  │  (Proxy Admin)       │       │  0x170ff0...                  │  │
│  │  0x0265...           │       │                               │  │
│  │  Owner: Concrete 3/5 │       │  - Reports value via diff     │  │
│  │  0xdc29...           │       │  - Holds Senior Tranche tokens│  │
│  └──────────────────────┘       └──────────────┬────────────────┘  │
│                                                │                    │
└────────────────────────────────────────────────┼────────────────────┘
                                                 │
                                    holds ST tokens / redeems
                                                 │
┌────────────────────────────────────────────────┼────────────────────┐
│                   ROYCO DAWN TRANCHING LAYER   │                    │
│                                                ▼                    │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │  RoycoFactory Proxy (AccessManager)  0x7cC6...              │  │
│  │  Manages roles for all Dawn contracts (DEPLOYER, LP, SYNC)  │  │
│  └────────────────────────────┬─────────────────────────────────┘  │
│                               │ deploys & governs                   │
│               ┌───────────────┼───────────────┐                     │
│               ▼               ▼               ▼                     │
│  ┌─────────────────┐ ┌──────────────┐ ┌──────────────────┐        │
│  │  PER-MARKET SET  │ │              │ │                  │        │
│  │  (×2 active)     │ │  Neutrl      │ │  Tokemak         │        │
│  │                  │ │  sNUSD       │ │  autoUSD         │        │
│  │ ┌──────────────┐│ │  Market      │ │  Market          │        │
│  │ │   Kernel     ││ │              │ │                  │        │
│  │ │ stDeposit()  ││ │ fixedTerm=0  │ │ fixedTerm=2days  │        │
│  │ │ stRedeem()   ││ │ liqUtil=100% │ │ liqUtil=122.5%   │        │
│  │ │ jtDeposit()  ││ └──────────────┘ └──────────────────┘        │
│  │ │ jtRedeem()   ││                                               │
│  │ │ setConversion││                                               │
│  │ │  Rate()      ││                                               │
│  │ └──────┬───────┘│                                               │
│  │        │        │                                               │
│  │ ┌──────▼───────┐│  ┌──────────────┐  ┌──────────────────┐      │
│  │ │  Accountant  ││  │Senior Tranche│  │ Junior Tranche   │      │
│  │ │  getState()  ││  │ (ERC-4626)   │  │ (ERC-4626)       │      │
│  │ │  coverage    ││  │ ROY-ST-*     │  │ ROY-JT-*         │      │
│  │ │  NAV sync    │◀─▶│              │  │                  │      │
│  │ │  loss waterf.││  │ Held by      │  │ Held by 2-3      │      │
│  │ │  market state││  │ Treasury     │  │ independent      │      │
│  │ └──────────────┘│  │ multisig     │  │ depositors       │      │
│  │                  │  └──────────────┘  └──────────────────┘      │
│  └─────────────────┘                                               │
│                                                                     │
│  ┌──────────────────────────────────────────────────────────────┐  │
│  │  AdaptiveCurveYDM (Immutable)  0x071B...                    │  │
│  │  Determines JT yield share (risk premium). No admin.        │  │
│  └──────────────────────────────────────────────────────────────┘  │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘
                                │
                    deposits yield-bearing assets
                                │
┌───────────────────────────────┼─────────────────────────────────────┐
│              UNDERLYING YIELD PROTOCOLS                              │
│                               ▼                                     │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐              │
│  │  Neutrl      │  │  Tokemak     │  │  Aave v3     │              │
│  │  (sNUSD)     │  │  (autoUSD)   │  │  (USDC)      │              │
│  │  35% target  │  │  10% target  │  │  20% target  │              │
│  └──────────────┘  └──────────────┘  └──────────────┘              │
│  ┌──────────────┐  ┌──────────────┐                                 │
│  │  Avant       │  │  Cap Finance │                                 │
│  │  (savUSD)    │  │  (stcUSD)    │                                 │
│  │  35% target  │  │  Paused      │                                 │
│  └──────────────┘  └──────────────┘                                 │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────────┐
│                        GOVERNANCE                                   │
│                                                                     │
│  Owner Multisig (3/5)          VAULT_MANAGER (3/4)                 │
│  0x85de42...                   0x7c405b...                         │
│  - Vault owner                 - Fee management                    │
│  - MultisigStrategy upgrade    - Queue toggles                     │
│    (NO TIMELOCK)                                                    │
│                                                                     │
│  Treasury Multisig (3/5)       ConcreteFactory Owner (3/5)         │
│  0x170ff0...                   0xdc29BD... (Concrete team)         │
│  - adjustTotalAssets()         - Vault implementation upgrades     │
│  - Holds Senior Tranche tokens                                     │
│                                                                     │
│  ⚠ Owner & Treasury share same 5 signers (no separation of powers)│
│  ⚠ VAULT_MANAGER shares 3 of 5 + 1 additional                    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘

Data flow: User deposits USDC → srRoyUSDC vault → MultisigStrategy
→ Treasury multisig deploys to Dawn Senior Tranches → Kernel routes
to underlying protocols. Value reported back via adjustTotalAssets().