This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
A yield farming aggregator: YieldAggregator.sol routes user deposits through protocol adapters (AaveV3Adapter.sol, CompoundV3Adapter.sol) implementing a shared IProtocolAdapter interface (deposit/withdraw/getShareValue). Auto-compounding/strategy-switching is planned via a Chainlink CRE keeper (see yield-aggregator-compounder/) but not yet implemented.
The repo has three distinct areas with separate toolchains:
src/,test/,lib/— the Foundry/Solidity contracts (primary focus of most work)frontend/— Next.js 15 + RainbowKit + wagmi dapp (ownpackage.json,npm run dev)yield-aggregator-compounder/— Chainlink CRE workflow (YAML config, not Solidity)
onboarding.md (a security-review onboarding doc) is a more accurate architecture reference than README.md, which is mostly empty headers.
CI (.github/workflows/test.yml) runs, in order:
forge fmt --check
forge build --sizes
forge test -vvv
Match this before considering contract work done.
- Fork tests hit live Ethereum mainnet (
vm.createSelectFork("mainnet_eth")intest/unit/YieldAggregatorTest.t.solandtest/fuzz/Invariants.t.sol), usingdeal()-funded USDC against real Aave/Compound deployments. They require a working RPC URL.foundry.toml'smainnet_ethendpoint reads${ETH_MAINNET_RPC_URL}— note thatonboarding.mddocuments a different variable name (MAINNET_RPC_URL); when in doubt,foundry.tomlis what Foundry actually reads. StrategyManager.solis excluded from compilation viafoundry.toml'sskiplist — it's an intentional stub (all internal functions are no-ops), not a build error.OracleLib.solis also an intentional empty placeholder for future work.foundry.toml[lint]excludesmixed-case-functionandcustom-errorsfrom enforcement.- Invariant tests run with
runs = 1000, depth = 128, fail_on_revert = false. - No
script/directory exists yet — there is no forge-script deployment flow in this repo currently.
- Custom errors only, no
requirestrings. Namespaced asContractName__ErrorName(e.g.YieldAggregator__InsufficientBalance). - File/contract layout follows the Cyfrin/Patrick-Collins convention: version pragma → imports → errors, then type declarations → state variables → events → modifiers → functions (constructor/receive/fallback/external/public/internal/private/view-pure), with
////... SECTION ...////banner comments dividing groups. - NatSpec (
@title,@author,@notice,@dev) is expected on contracts and most functions/errors.
getPositionValue/getYieldEarnedare notview— they call into live adapter state.- Withdrawal uses swap-and-pop on the positions array, which shifts indices; off-chain caches of position index can go stale.
YieldAggregator__InvalidSharesReceivedis effectively dead code.- No minimum-deposit enforcement — dust/rounding risk, especially in the Compound V3 adapter.
AaveV3Adapterwithdrawals deliberately subtract 1 wei as a rounding buffer to avoidNOT_ENOUGH_AVAILABLE_USER_BALANCEreverts — this is intentional, not a bug.