This analysis serves as an addendum to our initial analysis of Cap Protocols cUSD and stcUSD. The main areas covered include
- A technical review of all the smart contracts of the cUSD and stcUSD and their main dependencies, including Layerzero cross-chain configs.
- An update on material changes and liquidity conditions
- Parameter recommendations
Summary
LlamaRisk supports the onboarding of stcUSD. Although both Cap assets have been evaluated, following discussions with service providers and the respective teams, the preference is to commence onboarding with stcUSD only at this stage.
This is a technical review of the key smart contracts for cUSD and stcUSD, along with their main dependencies.
Asset Description
Cap USD (cUSD) is a U.S. dollar stablecoin with underlying reserves consisting of institutional-grade stablecoins, including USDC and WTGXX. cUSD is 1:1 collateralized by these onchain assets and can be redeemed on the same basis.
Staked Cap USD (stcUSD) is a yield-bearing stablecoin that generates yield from underlying cUSD collateral, allocated to various yield strategies curated by institutional investors, called âOperatorsâ.
Technical Analysis
The focus of our technical analysis includes the following aspects, critical for the correct and secure integration with Aave:
- A recommendation of a pricing strategy to be used in the Aave integration.
- Mechanism to update the exchange rate of the asset for the underlying.
- Analysis of the access control (ownerships, admin roles) and the nature of the entities involved in the system. Regarding the table permissionsâ holders and their criticality/risk, it is done following these guidelines:
| Criticality |
Description |
| Critical |
Grants super-admin capabilities that could fundamentally compromise the system, resulting in loss of funds if misused or exploited. (e.g., proxy admin, default admin roles) |
| High |
Governs multiple system components with meaningful exposure to fund loss if misused or exploited. (e.g., general owners or admin roles involved in the flow of funds) |
| Medium |
Can trigger malfunctions or minor financial losses if misused or exploited. (e.g., adjusting rates and fees, fee recipient addresses) |
| Low |
Can cause malfunctions in non-critical areas without direct financial impact. (e.g., updating descriptions or certain non-critical parameters) |
| Risk |
Description |
 |
Control mechanisms are robust, providing strong protection for the system and its users. Measures often include on-chain governance, a timelock contract, and multi-sigs under certain circumstances. |
 |
Control mechanisms introduce some risk exposure, depending on the scope of actions available. |
 |
Control mechanisms are inadequate and not secure, posing a direct risk to the system and its users. |
Contracts
The following is a non-exhaustive overview of the main smart contracts for cUSD and stcUSD related to the main protocol functions, i.e., collateralized borrowing.
CapToken
Deployed behind an upgradable ERC1967Proxy contract, the CapToken contract integrates minting and burning operations for cUSD and asset management functions for underlying assets within its vault structure. Implementing Oppenzepplinâs proxy standard, the implementation contract directs to this address. CapToken inherits from the Vault and UUPSUpgradeable contracts, which affects upgrades via the proxy.
Operations
-
Mint: Any user can mint new CapTokens by depositing an underlying asset by calling the mint() function. Internally, getRemainingMintCapacity() checks the deposit cap and truncates _amountIn if it exceeds the remaining capacity. The contract then calls Minter.getMintAmount() to calculate amountOut and fee. Mint fees set are sent to the insurance fund.
- The insurance fund is a 2/3 Multisig, and currently holds $500K denominated in cUSD and USDC.
-
Burn: Users can burn vault tokens to receive a single underlying asset by calling the burn() function. Internally, getBurnAmount() calculates the underlying amountOut and fee. The vault verifies that it has a sufficient balance of the underlying asset via the divest() function. Finally, VaultLogic.burn() enforces slippage and deadline checks, with the fee retained in the vault and amountOut sent to the receiving address.
-
Redeem: Users can redeem vault tokens for a proportional share of every underlying asset in the vault by calling the redeem() function. The contract calls _burn() to destroy the vault tokens upfront, and the vault then verifies that a sufficient balance of each underlying asset is available. Fees are retained in the vault.
-
Borrow: Permissioned addresses with borrow access can borrow underlying assets by calling the borrow() function. The checkAccess() modifier restricts callers. divest() verifies the vault has sufficient balance. Finally, VaultLogic.borrow() updates totalBorrows[_asset] and transfers _amount to _receiver.
-
Repay: Permissioned addresses with repay access can repay borrowed assets by calling the repay() function. The checkAccess(this.repay.selector) modifier restricts callers. VaultLogic.repay() decreases totalBorrows[_asset] and transfers _amount of _asset from the message sender to the vault (requires prior ERCâ20 approval). The function does not verify that the repayer is the original borrower.
-
Add/Remove Asset: Admin addresses can add or remove an underlying asset to the vault by calling the addAsset(_asset) or removeAsset(_asset) functions. The checkAccess() modifier restricts callers.
-
Pause/Unpause Asset: Admin addresses can pause and unpause a specific asset by calling the unpauseAsset(_asset) or pauseAsset(_asset) functions. The checkAccess() modifier restricts callers.
-
Pause Protocol: Permissioned users can pause the entire protocol by calling the pauseProtocol() function. The checkAccess() modifier restricts callers. The internal _pause() function from OpenZeppelinâs PausableUpgradeable activates the whenNotPaused modifier on mint, burn, redeem, borrow, and repay, temporarily locking all user funds.
-
Unpause Protocol: Permissioned users can unpause the entire protocol by calling the unpauseProtocol() function. The checkAccess() modifier restricts callers. The internal _unpausefunction deactivates the global pause, resuming all operations.
-
Upgrade: Admin can upgrade the proxy implementation logic by calling: upgradeTo(address newImplementation).
Access Control
All permissioned functions are validated by the checkAccess method in the Access Control contract, which determines whether the caller can operate.
stakedCap
Deployed behind an upgradable ERC1967Proxy contract, StakedCap is an ERC4626 yield-bearing vault that integrates minting and burning operations for staked Cap tokens and manages the vesting logic for newly accrued yield from the underlying asset.
Operations
- Deposit and Mint: Users can deposit the underlying cUSD and receive stcUSD tokens by calling
deposit(). It calculates shares via previewDeposit(assets) and calls _deposit() , which updates storedTotal += assets. Minting is enacted by mint() function, calculating the required assets via previewMint(shares) and calling the same _deposit logic. Staked Cap tokens are minted to the receiver.
- Withdrawal and Redeem: Users can redeem shares for underlying assets by calling
redeem(), which burns a specific number of shares and sends the underlying assets. Uses previewRedeem(shares) to calculate assets returned. Users can withdraw using withdraw(), which withdraws a specific amount of underlying assets. Uses previewWithdraw(assets) to calculate shares burned.
- Yield Notification: Anyone can notify new yield accrual by calling notify(), which starts linear unlock of newly deposited yield.
- Upgrade: Admin can upgrade the proxy implementation logic by calling:
upgradeTo(address newImplementation), inherited from UUPSUpgradeable.
Access Control
DebtToken
The DebtToken contract integrates minting and burning operations for debt tokens representing borrowed assets, with automatic interest accrual and interest rate management functions within its lending market structure. The contract relies on an oracle to fetch market, benchmark, and utilization rates, which determine the dynamic interest rate applied to all debt positions. Each mint or burn operation triggers an index update that compounds interest and recalculates the current interest rate.
Operations
-
Mint: Lender can mint debt tokens representing borrowed assets by calling mint()==,== minting debt tokens to a specified address. Internally calls _updateIndex() to refresh the accrual index before minting, then _mintScaled(), which scales the minted amount by the current debt index.
-
Burn: Lender burns debt tokens (repays debt) by calling burn(). Internally calls _updateIndex() to refresh the accrual index before burning, then _burnScaled(), it scales the burned amount by the current debt index.
-
Interest Rate Accrual: The contract automatically accrues interest when any mint or burn occurs by calling _updateIndex()
-
Debt Calculation: View functions for accrued interest include;
balanceOf(): Returns _balanceOfScaled(), which multiplies the userâs scaled balance by the current index.
totalSupply(): Returns _totalSupplyScaled(index()), showing total debt, including accrued interest.
index(): Returns the current debt index.
-
Upgrade: Admin can upgrade the proxy implementation logic by calling: upgradeTo(address newImplementation), inherited from UUPSUpgradeable.
Access Control
Oracle
The Oracle contract unifies price and rate oracle functionality, providing asset prices, market rates, benchmark rates, and utilization rates to determine dynamic borrowing costs across debt positions.
Operations
-
Rate Queries: External contracts can fetch market rates, benchmark rates, or utilization rates by calling rate getter functions inherited from PriceOracle and RateOracle. Current Oracles:
- Price: USDC ChainlinkAdapter, wWTGXX FixedPriceOracle
- Rate: USDC AaveAdapter, wWTGXX (none)
Lender
The Lender contract manages borrowing and repayment of whitelisted tokens by Operators (covered agents), calculating interest based on asset utilization rates within vaults. Lender inherits from UUPSUpgradeable, Access, and LenderStorageUtils, which affects upgrades via the proxy.
Operations
-
Borrowing: Agents can borrow assets by calling the borrow() function. Internally, it calls BorrowLogic.borrow with parameters including the agent, asset, amount, receiver, and a maxBorrow flag set to true if the amount is type(uint256).max. The borrowing process includes checks for agent eligibility (whitelisting via AccessControl), Sufficient collateral and delegation to back the borrow, and borrow amount not exceeding the maximum borrowable amount (maxBorrowable), and health factor remaining above the targetHealth after the borrow (among other checks).
-
Repay: Agents can repay borrowed assets by calling the repay() function. Internally, it calls BorrowLogic.repay with the agent, asset, amount, and caller (msg.sender) as parameters.
-
Interest Management: Anyone can realize accrued interest for an asset by calling the realizeInterest() function. Internally, it calls BorrowLogic.realizeInterest, which calculates accrued interest based on utilization rates and adds it to the reserveâs interest receiver.
-
Restaker Interest: Restakers can realize their specific accrued interest by calling the realizeRestakerInterest() function. Internally, it calls BorrowLogic.realizeRestakerInterest, which calculates and transfers the interest earned by a restaker for a specific agent-asset pair.
-
Liquidations:
- Opening: Any user can open a liquidation for an unhealthy agent by calling the
openLiquidation(agent) function. Internally, it calls LiquidationLogic.openLiquidation, which checks if the agentâs health factor has fallen below the emergencyLiquidationThreshold and records the start time.
- Closing: Users can close a liquidation by calling the
closeLiquidation(agent) function. Internally, it calls LiquidationLogic.closeLiquidation, which removes the agent from liquidation status.
- Liquidation Repayment: Liquidators can repay agent debt and receive collateral by calling the
liquidate() function. Internally, it calls LiquidationLogic.liquidate with repayment parameters and a minimum acceptable liquidation value.
-
Asset Management:
- Add Asset: Permissioned users can add an asset by calling the
addAsset() function. The AddAssetParams struct includes asset address, vault, debt token, decimals, interest receiver, and min borrow amount. Internally, it calls ReserveLogic.addAsset and increments reservesCount.
- Remove Asset: Authorized users can remove an asset by calling the
removeAsset() function. Internally, it calls ReserveLogic.removeAsset.
- Pause/Unpause: Authorized users can pause/unpause an asset by calling the
pauseAsset() function.
Access Control
Delegation
The Delegation contract manages slashing, reward distribution, and coverage calculations for restakers providing coverage to borrowers within a symbiotic network middleware architecture. The contract tracks agent-specific parameters, including loan-to-value (LTV) ratios and liquidation thresholds. In the contract context, an Operator is a trusted entity that manages the delegation system that enables agents to borrow.
Operations
-
Agent Management:
- Adding Agents: Operators can add new agents by calling the
addAgent() function. Internally, it validates that LT does not exceed 100% and is non-zero, and ensures the agent is not a duplicate via agents.add(). The function then stores the agentâs network, LTV, and liquidation threshold
- Managing Agents: Operators can modify existing agents via
modifyAgent(), which performs the same validation checks and updates the agentâs parameters after verifying existence via agents.contains(_agent).
-
Network Registration: Operators can register new networks by calling registerNetwork(). The function validates that _network is not the zero address, adds the network to the networkâs enumerable set via networks.add(), which reverts with DuplicateNetwork if already present.
-
Slashing: Operators can slash an agent by calling slash(). The slashShare is calculated as _amount * 1e18 / networkSlashableCollateral.
-
Reward distribution: Anyone can distribute rewards by calling distributeRewards(). The function retrieves the contractâs balance of _asset via IERC20(_asset).balanceOf(address(this)). If coverage(_agent) returns zero; the entire amount is transferred to feeRecipient.
-
Coverage Query: Users can query an agentâs effective coverage by calling coverage(_agent).
Access Control
Vault Adapter
The VaultAdapter contract calculates dynamic interest rates for assets in external vaults using utilization data and configurable slope parameters. The contract tracks utilization per vault-asset pair, applies a piecewise rate curve around a kink threshold, and adjusts a time-sensitive multiplier.
Operations
- Interest Rate Calculation: The contract calculates interest rates based on vault utilization by calling the
rate() function. Internally, it retrieves stored utilization data, including the last update timestamp and utilization index. Internal function applies the rate logic based on where utilization falls relative to the configured kink point.
- Modify Slopes: Permissioned users can modify rate curve parameters by calling
setSlopes(). This function validates that the kink value is neither zero nor greater than or equal to 100%, then stores the slope0, slope1, and kink values for the specified asset.
- Modify Limits: Permissioned users can modify global multiplier limits and adjustment speed by calling
setLimits(). This function updates the stored maxMultiplier, minMultiplier, and rate values that control how quickly the dynamic multiplier moves toward its bounds.
Access Control
Network Middleware
The SymbioticNetworkMiddleware contract (likewise with the EigenLayer version) manages collateral, slashing, and reward distribution for agents within a Symbiotic-based network. It integrates with Symbiotic vaults to register coverage, slash operators based on oracle prices, and route rewards to staker rewarders.
Operations
-
Vault Registration: Permissioned users register a vault for agents by calling registerVault(). The function checks caller access, verifies that the agent is not already registered, and then calls the internal _verifyVault() function, which validates that the vault exists in the registry and has the correct configuration. Vaults are created by the vaultFactory (CapSymbioticVaultFactory) contract, which deploys new vaults compliant with the Cap system.
- When the
createVault function is called, the _asset parameter (the collateral address) is passed into the vaultâs initialization parameters, along with configurable deposit and slashing parameters.
-
Slashing: Permissioned callers can slash an agent via slash(). The function retrieves the agentâs vault, calculates slashable collateral via slashableCollateralByVault(), then computes the actual slash amount.
-
Reward Distribution: Permissioned callers distribute rewards via distributeRewards().
Access Control
AccessControl
The AccessControl contract provides granular role-based access control for contract functions, enabling access rights for specific functions within specific contracts. The contract inherits from AccessControlEnumerableUpgradeable from OpenZeppelin.
Operations
- Grant Access: Permssioned users can grant function-level access to a specific contract by calling the
grantAccess() function. Internally, it checks that the caller has the grant access role via _checkRole(). It then creates a unique role ID assigned to the specific contract.
- Revoke Access: Admins can revoke function-level access by calling
revokeAccess(). Internally, it checks that the caller has the revoke access role via _checkRole(role(). The contract prevents self-revocation.
Access Control
TimelockController
The TimelockController contract integrates role-based access control and time-locked execution into its modular structure for governance operations. TimelockController inherits from AccessControl, which enables it to enforce a minimum delay on scheduled operations. The current minimum delay set is 24 hours.
Access Control
| Function |
Persmission |
Criticality |
Risk |
| schedule |
PROPOSER_ROLE |
CRITICAL |
 |
| scheduleBatch |
PROPOSER_ROLE |
CRITICAL |
 |
| execute |
EXECUTOR_ROLE |
CRITICAL |
 |
| executeBatch |
EXECUTOR_ROLE |
CRITICAL |
 |
| cancel |
CANCELLER_ROLE |
HIGH |
 |
| updateDelay |
Internal |
CRITICAL |
â |
| grantRole |
DEFAULT_ADMIN_ROLE |
CRITICAL |
 |
| revokeRole |
DEFAULT_ADMIN_ROLE |
CRITICAL |
 |
Roles
L2TokenUpgradeable
The L2TokenUpgradeable contract, which the cUSD and stcUSD MegaETH proxy deployments point to, implements cross-chain token functionality using LayerZeroâs OFT (Omnichain Fungible Token) standard, combining ERC20 features for gasless approvals and UUPS upgradeability.
Operations
- Cross-Chain Send: User calls
send(), this function internally calls _debit(), which burns the userâs tokens on the source chain. The function then calls _lzSend() to send a LayerZero message to the destination chain. The LayerZero endpoint delivers the message on the destination chain following verification by the configured DVNs.
- Cross-Chain Receive: the LayerZero endpoint calls the
lzReceive() function, which extracts the recipient address and amount, then calls _credit() and subsequently calls the internal _mint() function.
Access Control
OFTLockboxUpgradeable
The mainnet bridge sits behind an ERC1967Proxy and serves as the LayerZero OFT Adapter lockbox, with the implementation OFTLockboxUpgradeable contract. The mechanism holds the canonical assets on the chain and facilitates cross-chain transfers via a lock-and-release mechanism for the underlying assets. Upgrades flow through the proxyadmin, authorized exclusively by the contract owner.
Operations
- Cross-chain Send: users can bridge tokens by calling
send function from the inheritedOFTAdapterUpgradeable. The adapter locks the underlying token in the lockbox and emits a LayerZero message to the destination chainâs OFT peer, where an equivalent amount is minted or released.
- Cross-chain Receive: Inbound messages from LayerZero peers are processed via the inherited
_lzReceive handler. The lockbox unlocks and transfers the underlying token to the recipient on the home chain upon receipt of a verified cross-chain message.
- Peer Management: The OApp owner can configure trusted remote peers by calling the inherited
setPeer function. This determines which destination-chain contracts are authorized to send and receive messages through this adapter.
- DVN / Enforced Options Configuration: The OApp owner can set send and receive library configurations and enforced messaging options (e.g., DVN sets, executor, gas limits) via the LayerZero endpoint.
- Delegate Management: The OApp owner can reassign the delegate (the address authorized to make OApp configuration changes) via the inherited
setDelegate() function on the LayerZero endpoint.
- Upgrade: The owner can upgrade the implementation contract by calling
upgradeToAndCall, authorized through _authorizeUpgrade which enforces onlyOwner.
Access Control
Bridge Configuration
Cap Protocol uses LayerZeroâs OFT standard with a 3/0 DVN setup. Funds locked on mainnet before being minted on MegaETH. The protocol recently switched to the 3/0 setup comprising LayerZero Labs, Nethermind, and Canary.
| Asset |
OFT Adapter |
SourceChain |
requiredDVNs |
optionalDVNs |
confirmations |
| cUSD |
OFTLockbox 1 |
Ethereum |
3 |
0 |
15 |
| stcUSD |
OFTLockbox 2 |
Ethereum |
3 |
0 |
15 |
The required DVNs:
This setup can be considered reasonably secure, not relying on a quorum not as prone to exposure. cUSD and stcUSD are only available on Ethereum and MegaETH. At the time of writing 660K stcUSD is currently locked in the mainnet bridge.
Technical Conclusion
Based on our assessment, we believe cUSD and stcUSD do not have significant infrastructure barriers to listing; however, we identified technical implementations that could pose potential security risks to usersâ funds on the Aave Protocol. We summarized the risk considerations below.
- Vault: The
pauseProtocol() function allows the admin to globally pause all withdrawals (mint, burn, redeem). The Cap Deployer contract retains this privilege; if compromised, this could lock all user funds and freeze the protocol until the Multisig unfreezes it.
Additionally, the MegaETH OFTs were initially owned by the 3/5 multisig, which was able to effect an upgrade without delay. Following engagement with the Cap team, ownership has since been transferred to the TimelockController, which applies a 1-day delay. This security measure enhances the original implementation and aligns with the security framework applied to other critical operations.
Fundamental Analysis Update
Asset Classification
stcUSD remains a yield-bearing stablecoin, comparable to already-onboarded assets such as syrupUSDC/USDT. Thus, staked cUSD complies with an accepted asset classification under AAcA.
Multi-Chain Scope
stcUSD is available on Ethereum, MegaETH, and Tempo via LayerZero OFT. While mainnet and MegaETH represent chains that Aave has deployed on, Tempo has yet to be fully assessed. stcUSD can be bridged interchangeably between these. LZ OApp configurations between chains remain consistent, i.e., DVN sets persist as message senders and receivers.
cUSD and stcUSD on Tempo uses a TempoBridgeUpgradeable contract to bridge between the 2 available routes. The LayerZero OFT adapter bridges the TIP20 Tempo standard (ERC20 equivalent) of the Cap token between Tempo and the EVM chains, using the same mint/burn pattern. The bridge employs an ownable pattern, with the following operations.
- Cross-chain Send: Caller approves the bridge, then calls
send. Bridge pulls tokens via transferFrom, burns them, and emits a LayerZero message to the destination peer to mint an equivalent amount.
- Cross-chain Receive: Inbound LZ messages are processed via
_lzReceive. Bridge calls mint on the TIP-20 to credit the recipient directly.
- Peer Management: Owner calls
setPeer to configure trusted remote contracts. Governs which destination-chain addresses may send and receive messages through this bridge.
- DVN / Enforced Options Configuration: Owner sets send/receive library configs and enforced messaging options (DVN sets, executor, gas limits) via the LayerZero endpoint.
- Delegate Management: The owner can call
setDelegate to reassign the address authorized to make OApp configuration changes.
- Upgrade: Owner can call
upgradeToAndCall.
Access Control
While the Tempo chain has not been analyzed previously, the bridging mechanism follows established LZ mechanisms. Access controls on the bridge follow the same Timelock-controlled permissions access.
Asset Backing Structure and Visibility
Cap idle reserves are currently held in Morpho vaults, which represent ~34% of total reserves. The Cap team indicated that this setup is being changed, with idle reserves being moved to TBill products via partners such as Ondo.
Additionally, collateral assets, which consist of Aave (wstETH and weETH) and non-Aave onboarded assets (uniBTC and solvBTC), will evolve to enable RWAs as eligible collateral.
Source: Assets in Reserve, Cap Protocol, June 12th, 2026
Underlying assets are predominantly held in USDC (>93%) with the remaining held in WTGXX. This remains consistent with our initial analysis. At present, exit liquidity remains accessible from lending protocols.
Operators
Currently, there are 30 whitelisted borrowers, of whom 15 are active and have borrowed $42.3M. Their health scores over 120%. This represents an increase since our initial analysis, which saw $16.88M lent to 6 operators.
Source: Operator Loans, Cap Protocol, June 12th, 2026
Relative to our initial observation, the LTV/LT Ratio map indicates that loans have improved their overall scores, with fewer borrowers near the liquidation threshold. The team indicated that a more in-depth dashboard was being developed with greater visibility on parameters and operator loan health.
The protocol supports per-vault exposure limits, allowing collateral concentration risk to be managed at the individual asset or underwriter level. Coverage caps are already active for several underwriters, with the team indicating that the framework is applicable across the collateral base when required.
Restakers
Underwriters (i.e., Delegators) to loans have increased from 17 to 22, with the combined delegation growing to $213.52M from $74.05M.
Permitted collateral assets and parameters are determined by the Cap team. The current Loan to Value parameters:
- 50-60% LTV limits on volatile assets
- 80% LTV on stable assets
The current Liquidation Threshold parameters:
- 80% LT for volatile assets
- 85% LT on Stable assets
- 90% Emergency LT for all assets
At the vault level, per-asset liquidation thresholds are configured at deployment and are not intended to be adjusted, providing borrowers with predictable collateralization requirements and, upon breach, a 12-hour grace period during which they may repay outstanding debt before liquidation is triggered. The emergency 90% LT, which bypasses the grace period, functions as a circuit breaker, waiving the standard grace window due to protocol solvency risk.
The emergency liquidation bonus is dynamically capped at (collateral - debt) / debt. The bonus compresses as the collateral buffer narrows, ensuring that liquidations donât payout more than the liquidatable collateral, thereby pushing a position into bad debt. For example, at 91% LTV, the bonus ceiling is ~9%, and at 95% LTV, it falls to ~5%.
Slashing on Symbiotic
Within Symbioticâs Shared Security Network, Cap Protocol operates as a network, permitted to slash Operators whose assets are restaked to them. Networks define their own methods for penalizing Operators within the overall slashing framework, with the liquidations/slashing framework consisting of 4 primary contracts: Delegation, Vault, Network Middleware, and Burner Router. The slashing process on Symbiotic mirrors the liquidation process defined by the Cap protocol, and follows the following process:
- The Network Middleware contract sends a slashing request to a penalized vault
- The vaultâs Slasher module checks if the request is valid,
-
- Reads stake data from the Delegator and its own internal data (previous slashes).
- Guarantees that the collateral snapshot will remain slashable for one vault epoch after that timestamp (otherwise, it is considered stale and rejected).
- Checks that the amount constraint is within a slashable amount < remaining collateral.
- If valid, the vault updates its internal data and the Delegation contract
- Slasher calls The Vaultâs Burner module to process the penalized collateral.
Within this framework, networks choose which slashing configuration to implement for their model and which penalties enact slashing (e.g., redistributing stake, burning tokens, routing stake to a contract).
Cap Protocol Slashing Configuration
The configurations implemented by Cap Protocol for delegations and liquidations (Symbiotic Slashing) are summarized as follows:
Vaults
- Symbiotic Vaults are isolated per borrower. Immutability is enforced by
OperatorNetworkSpecificDelegator.
- Each borrower position is isolated to a single underwriter and collateral asset. When a vault is created, a new operator and vault instance are created (borrower position).
- Vaults implement an INSTANT slashing type, meaning the Slasher module is validated and executed in a single step (no dispute window).
Liquidations
- Liquidations are callable by anyone from the Lender contract via the
liquidate function after the openLiquidation window, which invokes IDelegation.slash to begin slashing the target vault.
- Liquidators repay up to
maxLiquidatable of the Operatorâs debt. The liquidation bonus implements a dynamic liquidation bonus system, with the bonus rising linearly until the 10% bonusCap during an auction window.
- The LB does not differ per asset, and under emergency liquidations, the 10% maximum applies immediately (when LTV exceeds the emergency LT).
- The vault reduces the operatorâs effective stake and forwards the penalized collateral to a Burner. Assets are seized and transferred through the
BurnerRouter.
BurnerRoute transfers assets upon a valid liquidation. Transfers route to the Network Middleware contract for all Cap protocol vaults.
- The Middleware contract transfers the funds to the liquidatorâs
_recipient address set when liquidate was called. Liquidators are compensated for the USDC repaid + applicable liquidation bonus.
- If the health score of the borrower recovers to â„ 1e27 (>100%) after the liquidation, the window closes. (Liquidations are only partial, up to a +25% health target recovery)
The protocol operates a layered liquidation infrastructure alongside its permissionless mechanism. The Cap team indicated that formalized liquidation agreements for specific collateral types are under negotiation with market makers. As a further backstop, the protocol operates a proprietary liquidation keeper capable of executing both atomic and non-atomic liquidations that require temporary treasury capital deployment. This multicontingent approach reduces reliance on permissionless liquidator participation during periods of market stress.
Historical Symbiotic Slashes
To date, there have been only 2 slash events on Symbiotic, all performed on Cap Protocol Vaults. Given the Operator, the slash amount, the Middleware address, and timing, these events were likely internal initial tests performed by the Cap protocol. Therefore, it is difficult to determine how effectively historic liquidations have been performed from the small dataset.
Token Holder Concentration
As of June 12th, 2026, cUSD has 478 holders and a total onchain supply of 209.9K. The largest 3 holders:
stcUSD currently has 197 holders and a total supply of 1.07M tokens onchain. Liquidity is concentrated with 3 holders:
Liquidity
stcUSD and cUSD liquidity remains low on MegaETH. The Cap protocol team has committed $2M to stcUSD liquidity on the Kumbaya DEX.
Source: cUSD/USDm Fly, June 12th, 2026
Source: stcUSD/USDm Kumbaya, June 12th, 2026
Source: cUSD Liquidity Pools on MegaETH, GeckoTerminal, June 12th, 2026
Source: stcUSD Liquidity Pools on MegaETH, GeckoTerminal, June 12th, 2026
Volatility
The cUSD/USDM pool lacks sufficient liquidity, creating frequent volatility around the intended $1 peg. The maximum and minimum price deviations observed were 1.03 and 0.97, respectively.
Source: cUSD/USDM pair, Dune, June 12th, 2026
Given the more recent Kumbaya pool deployment for stcUSD, market volatility data is limited. The sole pool of meaningful liquidity was launched on April 28th, 2026, making a relative comparison to the internal exchange rate impractical at this stage.
Source: stcUSD/USDM pair, GeckoTerminal, June 12th, 2026
Multisig Threshold / Signer identity
Signers are Cap Protocol members.
Aave V3 Specific Parameters
| Parameter |
Value |
| Asset |
stcUSD |
| E-Mode |
Stablecoin |
| Borrowable |
No |
| Collateral Enabled |
No |
| Supply Cap |
10,000,000 |
| Borrow Cap |
- |
| Debt Ceiling |
- |
| LTV |
- |
| LT |
- |
| Liquidation Bonus |
- |
| Liquidation Protocol Fee |
10% |
| Reserve Factor |
- |
| Base Variable Borrow Rate |
- |
| Variable Slope 1 |
- |
| Variable Slope 2 |
- |
| Uoptimal |
- |
stcUSD Stablecoin E-Mode
| Parameter |
Value |
| isolated |
True |
| LTV |
88% |
| LT |
90% |
| Liquidation Bonus |
4% |
| Asset |
stcUSD |
USDT0 |
USDM |
| Collateral |
Yes |
No |
No |
| Borrowable |
No |
Yes |
Yes |
Price Feed Recommendation
We recommend pricing stcUSD on MegaETH using the Chainlink stcUSD/cUSD exchange rate feed in conjunction with a base USDC/USD price feed and CAPO adapter. Both price feeds use a 0.5% deviation threshold and a 24-hour heartbeat.
While a cUSD/USD Chainlink price feed exists, the feed is an internal exchange rate feed, with the base feed necessitating a market price reference with the exchange-rate component for accurate price reporting for Aave. Given that >93% of cUSD is backed by USDC, we recommend this setup until the appropriate market rate feed is deployed.
CAPO Configuration.
The effective yield of stcUSD varies over time based on the selection of Operators, their approved strategies, and the idle liquidity deployed to DeFi protocols that earn passive yields. stcUSD yield has demonstrated minimal volatility over the past three months.
Source: stcUSD APY, Dune, June 12th, 2026
We recommend setting MINIMUM_SNAPSHOT_DELAY to 14 days and maxYearlyRatioGrowthPercent to 10.5%. This would help smooth short-term volatility, given the assetâs relatively recent deployment, thereby ensuring consistent pricing.
Disclaimer
This review was independently prepared by LlamaRisk, a DeFi risk service provider funded in part by the Aave DAO. LlamaRisk is not directly affiliated with the protocol(s) reviewed in this assessment and did not receive any compensation from the protocol(s) or their affiliated entities for this work.
The information provided should not be construed as legal, financial, tax, or professional advice.