Skip to content

feat(strategy): add Compound V3 (Comet) strategy facet#18

Merged
jayeshy14 merged 1 commit into
mainfrom
feat/compound-v3-strategy
Jun 14, 2026
Merged

feat(strategy): add Compound V3 (Comet) strategy facet#18
jayeshy14 merged 1 commit into
mainfrom
feat/compound-v3-strategy

Conversation

@jayeshy14

@jayeshy14 jayeshy14 commented Jun 14, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a compound*-prefixed strategy facet that supplies the vault's underlying asset to a Compound III (Comet) base market (cUSDCv3) and reports its position via Comet's rebasing balanceOf. Shape mirrors AaveStrategyFacet: Comet's balanceOf is a live-accruing rebasing balance, so the position needs no receipt-token bookkeeping and harvest is a no-op.

This gives the router a second deep-liquidity money market on Arbitrum (Aave ~$1.0B, Compound III among the top markets) with a different rate curve, so allocations diversify rather than duplicate Aave's risk profile.

What's included

  • IComet — minimal interface (supply / withdraw / balanceOf / baseToken, plus the getUtilization / getSupplyRate view rate-readers a curator uses to price the market on-chain). Trimmed to the facet's surface, matching IAavePool.
  • CompoundV3StrategyFacet — EIP-7201 slot vaultrouter.strategy.compound.
  • MockComet + 23 unit tests (no RPC needed).
  • CompoundV3Strategy.fork.t.sol — 4 tests against the live Arbitrum cUSDCv3 market, RPC-gated (auto-skips without ARBITRUM_RPC_URL).
  • StorageNamespaces — pins the new namespace literal to its erc7201 hash.

Design decisions (where it diverges from the Aave facet)

  1. Config validates comet.baseToken() == asset (the Morpho-style guard Aave lacks), so a market for the wrong asset can never be wired in.
  2. Withdraw clamps to the position — Comet would tip an over-withdraw into a borrow, so compoundWithdraw clamps the request to balanceOf and measures the underlying actually received.
  3. SUPPLY_ROUNDING_SLACK = 2 — Comet rounds principal down on supply, so a strict < amount check (like Aave's) would flake; a real fee-on-supply still trips the guard, and any reverting deposit becomes a per-strategy rebalance skip, not a bricked batch.
  4. harvest is a no-op — base interest auto-accrues into balanceOf. COMP incentive rewards accrue separately via CometRewards (a non-underlying token needing its own claim/sell/account path) and are intentionally out of scope.

Testing

forge test                                  # 194 passed, 0 failed, 4 skipped (fork, RPC-gated)
forge test --match-contract CompoundV3StrategyTest
ARBITRUM_RPC_URL=<rpc> forge test --match-path test/integration/CompoundV3Strategy.fork.t.sol

Live Arbitrum addresses used by the fork test: Comet cUSDCv3 0x9c4ec768c28520B50860ea7a15bd7213a9fF58bf, base USDC 0xaf88d065e77c8cC2239327C5EDb3A432268e5831.

Notes

  • Rebased onto main (which now contains the erc7201 slot conventions this work depends on); the diff is just the Compound facet.
  • Known boundary (shared by every strategy): the Vault has no strategy pull-back hook yet, so redeems succeed only up to the idle reserve. Tests document this rather than paper over it.

Adds a compound* prefixed strategy facet that supplies the vault's
underlying to a Compound III base market (cUSDCv3) and reports its
position via Comet's rebasing balanceOf, mirroring the aToken pattern of
the Aave facet.

- IComet: minimal interface (supply/withdraw/balanceOf/baseToken plus the
  getUtilization/getSupplyRate view rate-readers a curator uses on-chain)
- CompoundV3StrategyFacet: EIP-7201 slot vaultrouter.strategy.compound;
  validates baseToken == asset at config time, clamps withdraws to the
  position so they can never tip into a borrow, tolerates Comet's
  present-value rounding on supply, and no-ops harvest (base interest
  auto-accrues into balanceOf)
- MockComet + 23 unit tests (config gating, asset mismatch, supply and
  withdraw shortfall guards, over-request clamp, yield accrual, allocator
  rebalance routing/drain/skip paths, redeem boundary)
- CompoundV3Strategy.fork.t.sol: 4 tests against the live Arbitrum
  cUSDCv3 market (RPC-gated, auto-skips without ARBITRUM_RPC_URL)
- StorageNamespaces: pin the new namespace literal to its erc7201 hash
@jayeshy14 jayeshy14 force-pushed the feat/compound-v3-strategy branch from c3b585b to 75d615c Compare June 14, 2026 08:13
@jayeshy14 jayeshy14 changed the base branch from refactor/erc7201-storage-standardization to main June 14, 2026 08:13
@jayeshy14 jayeshy14 merged commit eb85da2 into main Jun 14, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant