/** * Yield protocol constants — contract addresses, function selectors, and types * for Aave V3 and Morpho Blue vault integrations. */ // ── Supported chains for yield ── export type SupportedYieldChain = "1" | "8453"; export type YieldProtocol = "aave-v3" | "morpho-blue"; export type StablecoinSymbol = "USDC" | "USDT" | "DAI"; export interface YieldOpportunity { protocol: YieldProtocol; chainId: SupportedYieldChain; asset: StablecoinSymbol; assetAddress: string; vaultAddress: string; // aToken for Aave, vault for Morpho apy: number; apy7d?: number; tvl?: number; poolId?: string; // DeFi Llama pool ID vaultName?: string; } export interface YieldPosition { protocol: YieldProtocol; chainId: SupportedYieldChain; asset: StablecoinSymbol; assetAddress: string; vaultAddress: string; shares: string; // raw shares/aToken balance underlying: string; // underlying asset value decimals: number; apy: number; dailyEarnings: number; annualEarnings: number; } export interface YieldSuggestion { type: "deposit" | "rebalance"; priority: "high" | "medium" | "low"; from?: { protocol: YieldProtocol; chainId: SupportedYieldChain; vaultAddress: string; apy: number }; to: YieldOpportunity; amount: string; amountUSD: number; reason: string; estimatedGasCostUSD: number; } // ── Stablecoin addresses per chain ── export const STABLECOIN_ADDRESSES: Record> = { "1": { USDC: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", USDT: "0xdAC17F958D2ee523a2206206994597C13D831ec7", DAI: "0x6B175474E89094C44Da98b954EedeAC495271d0F", }, "8453": { USDC: "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913", USDT: "0x0000000000000000000000000000000000000000", // not on Base DAI: "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb", }, }; export const STABLECOIN_DECIMALS: Record = { USDC: 6, USDT: 6, DAI: 18, }; // ── Aave V3 ── export const AAVE_V3_POOL: Record = { "1": "0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2", "8453": "0xA238Dd80C259a72e81d7e4664a9801593F98d1c5", }; // aToken addresses (receipt tokens for deposits) export const AAVE_ATOKENS: Record>> = { "1": { USDC: "0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c", USDT: "0x23878914EFE38d27C4D67Ab83ed1b93A74D4086a", DAI: "0x018008bfb33d285247A21d44E50697654f754e63", }, "8453": { USDC: "0x4e65fE4DbA92790696d040ac24Aa414708F5c0AB", DAI: "0x0a1d576f3eFeF75b330424287a95A366e8281D54", }, }; // ── Morpho Blue Vaults ── export interface MorphoVaultInfo { address: string; name: string; asset: StablecoinSymbol; } export const MORPHO_VAULTS: Record = { "1": [ { address: "0xBEEF01735c132Ada46AA9aA4c54623cAA92A64CB", name: "Steakhouse USDC", asset: "USDC" }, { address: "0x2371e134e3455e0593363cBF89d3b6cf53740618", name: "Steakhouse USDT", asset: "USDT" }, ], "8453": [ { address: "0xc1256Ae5FF1cf2719D4937adb3bbCCab2E00A2Ca", name: "Moonwell Flagship USDC", asset: "USDC" }, ], }; // ── MultiSend (for batched approve+deposit) ── export const MULTISEND_CALL_ONLY: Record = { "1": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", "8453": "0x40A2aCCbd92BCA938b02010E17A5b8929b49130D", }; // ── Function selectors ── export const SELECTORS = { // ERC-20 approve: "0x095ea7b3", // approve(address,uint256) balanceOf: "0x70a08231", // balanceOf(address) // Aave V3 Pool supply: "0x617ba037", // supply(address,uint256,address,uint16) withdraw: "0x69328dec", // withdraw(address,uint256,address) getReserveData: "0x35ea6a75", // getReserveData(address) // ERC-4626 (Morpho vaults) deposit: "0x6e553f65", // deposit(uint256,address) redeem: "0xba087652", // redeem(uint256,address,address) convertToAssets: "0x07a2d13a", // convertToAssets(uint256) maxDeposit: "0x402d267d", // maxDeposit(address) // MultiSend multiSend: "0x8d80ff0a", // multiSend(bytes) } as const; // ── ABI encoding helpers ── export function padAddress(addr: string): string { return addr.slice(2).toLowerCase().padStart(64, "0"); } export function padUint256(value: bigint): string { return value.toString(16).padStart(64, "0"); } export function encodeApprove(spender: string, amount: bigint): string { return `${SELECTORS.approve}${padAddress(spender)}${padUint256(amount)}`; } export function encodeAaveSupply(asset: string, amount: bigint, onBehalfOf: string): string { return `${SELECTORS.supply}${padAddress(asset)}${padUint256(amount)}${padAddress(onBehalfOf)}${padUint256(0n)}`; } export function encodeAaveWithdraw(asset: string, amount: bigint, to: string): string { return `${SELECTORS.withdraw}${padAddress(asset)}${padUint256(amount)}${padAddress(to)}`; } export function encodeMorphoDeposit(amount: bigint, receiver: string): string { return `${SELECTORS.deposit}${padUint256(amount)}${padAddress(receiver)}`; } export function encodeMorphoRedeem(shares: bigint, receiver: string, owner: string): string { return `${SELECTORS.redeem}${padUint256(shares)}${padAddress(receiver)}${padAddress(owner)}`; } export function encodeBalanceOf(address: string): string { return `${SELECTORS.balanceOf}${padAddress(address)}`; } export function encodeConvertToAssets(shares: bigint): string { return `${SELECTORS.convertToAssets}${padUint256(shares)}`; } export function encodeMaxDeposit(receiver: string): string { return `${SELECTORS.maxDeposit}${padAddress(receiver)}`; } // ── Chain display names ── export const YIELD_CHAIN_NAMES: Record = { "1": "Ethereum", "8453": "Base", };