1390/woofi-yield/SKILL.md
Comprehensive yield protocol reference covering Aave V3/V4, Spark (Savings + SparkLend), and Morpho V2 vaults — deposit/withdraw flows, contract interfaces, pool registries, and GraphQL APIs across 10+ chains. Essential for WOOFi ecosystem DeFi yield strategies.
npx skillsauth add starchild-ai-agent/community-skills @1390/woofi-yieldInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Aave V3 is the largest decentralized lending protocol. Users supply an underlying asset (e.g. USDC) and receive an aToken in return. aTokens are minted 1:1 with the supplied asset; their balance grows automatically over time to reflect accrued interest.
Key points:
supply() (renamed from V2's deposit())supplyWithPermit() is available for gasless approvals on EIP-2612 tokensSupported chains:
| Chain | chainId | |------------|---------| | Ethereum | 1 | | Arbitrum | 42161 | | Optimism | 10 | | Polygon | 137 | | Avalanche | 43114 | | Base | 8453 | | BNB Chain | 56 | | Gnosis | 100 | | Scroll | 534352 | | Linea | 59144 | | Sonic | 146 |
| Chain | chainId | Pool Address |
|------------|---------|----------------------------------------------|
| Ethereum | 1 | 0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2 |
| Arbitrum | 42161 | 0x794a61358D6845594F94dc1DB02A252b5b4814aD |
| Optimism | 10 | 0x794a61358D6845594F94dc1DB02A252b5b4814aD |
| Polygon | 137 | 0x794a61358D6845594F94dc1DB02A252b5b4814aD |
| Avalanche | 43114 | 0x794a61358D6845594F94dc1DB02A252b5b4814aD |
| Base | 8453 | 0xA238Dd80C259a72e81d7e4664a9801593F98d1c5 |
| BNB Chain | 56 | 0x6807dc923806fE8Fd134338EABCA509979a7e0cB |
| Gnosis | 100 | 0xb50201558B00496A145fE76f7424749556E326D8 |
| Scroll | 534352 | 0x11fCfe756c05AD438e312a7fd934381537D3cFfe |
| Linea | 59144 | 0xc47b8C00b0f69a36fa203Ffeac0334874574a8Ac |
| Chain | Underlying | aToken |
|------------|----------------------------------------------|----------------------------------------------|
| Ethereum | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 | 0x98C23E9d8f34FEFb1B7BD6a91B7FF122F4e16F5c |
| Arbitrum | 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8 | 0x625E7708f30cA75bfd92586e17077590C60eb4cD |
| Optimism | 0x7F5c764cBc14f9669B88837ca1490cCa17c31607 | 0x625E7708f30cA75bfd92586e17077590C60eb4cD |
| Polygon | 0x2791Bca1f2de4661ED88A30C99A7a9449Aa84174 | 0x625E7708f30cA75bfd92586e17077590C60eb4cD |
| Avalanche | 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E | 0x625E7708f30cA75bfd92586e17077590C60eb4cD |
| Base | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 | 0x4e65fE4DbA92790696d040ac24Aa414708F5c0AB |
| BNB Chain | 0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d | 0x00901a076785e0906d1028c7d6372d247bec7d61 |
| Gnosis | 0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83 | 0xc6B7AcA6DE8a6044E0e32d0c841a89244A10D284 |
| Scroll | 0x06eFdBFf2a14a7c8E15944D1F4A48F9F95F663A4 | 0x1D738a3436A8C49CefFbaB7fbF04B660fb528CbD |
| Linea | 0x176211869cA2b568f2A7D4EE941E073a821EE1ff | 0x374D7860c4f2f604De0191298dD393703Cce84f3 |
| Sonic | 0x29219dd400f2Bf60E5a23d13Be72B486D4038894 | 0x578Ee1ca3a8E1b54554Da1Bf7C583506C4CD11c6 |
Sonic, Scroll, and Gnosis do not have USDT reserves on Aave V3.
| Chain | Underlying | aToken |
|------------|----------------------------------------------|----------------------------------------------|
| Ethereum | 0xdAC17F958D2ee523a2206206994597C13D831ec7 | 0x23878914EFE38d27C4D67Ab83ed1b93A74D4086a |
| Arbitrum | 0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9 | 0x6ab707Aca953eDAeFBc4fD23bA73294241490620 |
| Optimism | 0x94b008aA00579c1307B0EF2c499aD98a8ce58e58 | 0x6ab707Aca953eDAeFBc4fD23bA73294241490620 |
| Polygon | 0xc2132D05D31c914a87C6611C10748AEb04B58e8F | 0x6ab707Aca953eDAeFBc4fD23bA73294241490620 |
| Avalanche | 0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7 | 0x6ab707Aca953eDAeFBc4fD23bA73294241490620 |
| BNB Chain | 0x55d398326f99059fF775485246999027B3197955 | 0xa9251ca9DE909CB71783723713B21E4233fbf1B1 |
| Linea | 0xA219439258ca9da29E9Cc4cE5596924745e12B93 | 0x88231dfEC71D4FF5c1e466D08C321944A7adC673 |
| Chain | Underlying | aToken | Note |
|------------|----------------------------------------------|----------------------------------------------|-----------|
| Ethereum | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 | 0x4d5F47FA6A74757f35C14fD3a6Ef8E3C9BC514E8 | |
| Arbitrum | 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1 | 0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8 | |
| Optimism | 0x4200000000000000000000000000000000000006 | 0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8 | |
| Polygon | 0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619 | 0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8 | |
| Avalanche | 0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB | 0xe50fA9b3c56FfB159cB0FCA61F5c9D750e8128c8 | WETH.e |
| Base | 0x4200000000000000000000000000000000000006 | 0xD4a0e0b9149BCee3C920d2E00b5dE09138fd8bb7 | |
| BNB Chain | 0x2170Ed0880ac9A755fd29B2688956BD959F933F8 | 0x2E94171493fAbE316b6205f1585779C887771E2F | ETH |
| Gnosis | 0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1 | 0xa818F1B57c201E092C4A2017A91815034326Efd1 | |
| Scroll | 0x5300000000000000000000000000000000000004 | 0xf301805bE1Df81102C957f6d4Ce29d2B8c056B2a | |
| Linea | 0xe5D7C2a44FfDDf6b295A15c148167daaAf5Cf34f | 0x787897dF92703BB3Fc4d9Ee98e15C0b8130Bf163 | |
| Sonic | 0x50c42dEAcD8Fc9773493ED674b675bE577f2634b | 0xe18Ab82c81E7Eecff32B8A82B1b7d2d23F1EcE96 | |
Sonic, Scroll, and Gnosis do not have WBTC reserves on Aave V3.
| Chain | Underlying | aToken | Note |
|------------|----------------------------------------------|----------------------------------------------|-----------|
| Ethereum | 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599 | 0x5Ee5bf7ae06D1Be5997A1A72006FE6C607eC6DE8 | WBTC |
| Arbitrum | 0x2f2a2543B76A4166549F7aaB2e75Bef0aefC5B0f | 0x078f358208685046a11C85e8ad32895DED33A249 | WBTC |
| Optimism | 0x68f180fcCe6836688e9084f035309E29Bf0A2095 | 0x078f358208685046a11C85e8ad32895DED33A249 | WBTC |
| Polygon | 0x1BFD67037B42Cf73acF2047067bd4F2C47D9BfD6 | 0x078f358208685046a11C85e8ad32895DED33A249 | WBTC |
| Avalanche | 0x50b7545627a5162F82A992c33b87aDc75187B218 | 0x078f358208685046a11C85e8ad32895DED33A249 | WBTC.e |
| Base | 0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf | 0xBdb9300b7CDE636d9cD4AFF00f6F009fFBBc8EE6 | cbBTC |
| BNB Chain | 0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c | 0x56a7ddc4e848EbF43845854205ad71D5D5F72d3D | BTCB |
| Linea | 0x3aAB2285ddcDdaD8edf438C1bAB47e1a9D05a9b4 | 0x37f7E06359F98162615e016d0008023D910bB576 | WBTC |
// Supply `amount` of `asset` to the pool on behalf of `onBehalfOf`
// referralCode is deprecated — pass 0
function supply(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
// Withdraw `amount` of `asset` from the pool, sending to `to`
// Pass type(uint256).max to withdraw the entire balance
function withdraw(
address asset,
uint256 amount,
address to
) external returns (uint256);
// Supply with EIP-2612 permit (gasless approval)
function supplyWithPermit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode,
uint256 deadline,
uint8 permitV,
bytes32 permitR,
bytes32 permitS
) external;
// Approve the Pool to spend underlying tokens on behalf of msg.sender
IERC20(underlying).approve(poolAddress, amount);
1. Resolve the Pool address and underlying token address for the target chain/asset.
2. Check user balance:
balance_raw = IERC20(underlying).balanceOf(user)
3. Approve Pool to spend underlying:
IERC20(underlying).approve(pool_address, amount_raw)
4. Execute supply:
pool.supply(underlying, amount_raw, user, 0)
→ User receives aTokens automatically (1:1 with supplied amount)
1. Resolve the Pool address and underlying token address.
2. Check aToken balance (= withdrawable amount):
aBalance_raw = IERC20(aToken).balanceOf(user)
3. Execute withdraw:
pool.withdraw(underlying, amount_raw, user)
→ aTokens are burned, underlying tokens sent to `user`
For full withdrawal, pass type(uint256).max as amount:
pool.withdraw(underlying, type(uint256).max, user)
Aave V3 does not accept native ETH directly. To supply/withdraw native ETH, use the WrappedTokenGatewayV3 contract:
// Deposit native ETH (wraps to WETH internally)
function depositETH(address pool, address onBehalfOf, uint16 referralCode) external payable;
// Withdraw to native ETH (unwraps WETH internally)
// User must approve aWETH to the gateway first
function withdrawETH(address pool, uint256 amount, address to) external;
Endpoint: https://api.v3.aave.com/graphql
query {
reserves {
chain { name chainId }
asset { underlying { symbol address } }
summary { supplyApy { normalized } borrowApy { normalized } }
canBorrow
canSupply
}
}
The supplyApy.normalized field returns the annualized supply rate as a decimal (e.g. 0.035 = 3.5% APY).
Aave V4 launched on Ethereum mainnet on 2026-03-30. It introduces a Hub-and-Spoke architecture: users interact with Spoke contracts, and funds flow to a shared Liquidity Hub. This replaces V3's per-chain isolated Pool model.
Key points:
supply() / withdraw() on a Spoke contract (not a Pool)reserveId (uint256) instead of asset addressreferralCode parameterSupported chains:
| Chain | chainId | |----------|---------| | Ethereum | 1 |
| Hub | Address |
|-------|----------------------------------------------|
| Core | 0xCca852Bc40e560adC3b1Cc58CA5b55638ce826c9 |
| Plus | 0x06002e9c4412CB7814a791eA3666D905871E536A |
| Prime | 0x943827DCA022D0F354a8a8c332dA1e5Eb9f9F931 |
| Spoke | Address |
|--------------------|----------------------------------------------|
| Main | 0x94e7A5dCbE816e498b89aB752661904E2F56c485 |
| Bluechip | 0x973a023A77420ba610f06b3858aD991Df6d85A08 |
| Lido E | 0xe1900480ac69f0B296841Cd01cC37546d92F35Cd |
| EtherFi E | 0xbF10BDfE177dE0336aFD7fcCF80A904E15386219 |
| Kelp E | 0x3131FE68C4722e726fe6B2819ED68e514395B9a4 |
| Ethena Correlated | 0x58131E79531caB1d52301228d1f7b842F26B9649 |
| Ethena Ecosystem | 0xba1B3D55D249692b669A164024A838309B7508AF |
| Lombard BTC | 0x7EC68b5695e803e98a21a9A05d744F28b0a7753D |
| Forex | 0xD8B93635b8C6d0fF98CbE90b5988E3F2d1Cd9da1 |
| Gold | 0x65407b940966954b23dfA3caA5C0702bB42984DC |
| Contract | Address |
|----------------------|----------------------------------------------|
| Native Token Gateway | 0xe68ab4F90Fe026B9873F5F276eD2d7efBbbE42Be |
| Signature Gateway | 0xfbC184337Dc6595D8bf62968Bda46e7De7AF9c3d |
| Token | Address |
|-------|----------------------------------------------|
| USDC | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 |
| USDT | 0xdAC17F958D2ee523a2206206994597C13D831ec7 |
| WETH | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
| WBTC | 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599 |
// Supply `amount` of the reserve identified by `reserveId` on behalf of `onBehalfOf`
// Returns (suppliedAmount, mintedShares)
function supply(
uint256 reserveId,
uint256 amount,
address onBehalfOf
) external returns (uint256, uint256);
// Withdraw `amount` of the reserve identified by `reserveId` on behalf of `onBehalfOf`
// Returns (withdrawnAmount, burnedShares)
function withdraw(
uint256 reserveId,
uint256 amount,
address onBehalfOf
) external returns (uint256, uint256);
// Approve the Spoke contract to spend underlying tokens on behalf of msg.sender
IERC20(underlying).approve(spokeAddress, amount);
1. Identify the target Spoke address and look up the reserveId for the asset (see Section 5).
2. Check user balance:
balance_raw = IERC20(underlying).balanceOf(user)
3. Approve Spoke to spend underlying:
IERC20(underlying).approve(spoke_address, amount_raw)
4. Execute supply:
(suppliedAmount, mintedShares) = spoke.supply(reserveId, amount_raw, user)
1. Identify the target Spoke address and look up the reserveId for the asset (see Section 5).
2. Execute withdraw:
(withdrawnAmount, burnedShares) = spoke.withdraw(reserveId, amount_raw, user)
→ Underlying tokens are sent to `user`
Aave V4 provides a Native Token Gateway for supplying/withdrawing native ETH without manual wrapping:
Gateway address: 0xe68ab4F90Fe026B9873F5F276eD2d7efBbbE42Be
Aave V4 identifies reserves by reserveId (uint256), not by asset address. To obtain the reserveId for a given asset, perform a two-step on-chain lookup:
// Step 1 — on the Hub contract
// Returns the Hub-internal asset ID for the given underlying token address
function getAssetId(address underlying) external view returns (uint256);
// Step 2 — on the Spoke contract
// Maps (hub, assetId) → reserveId used in supply()/withdraw()
function getReserveId(address hub, uint256 assetId) external view returns (uint256);
hub_address = <Hub address from Section 2> // e.g. Core Hub
spoke_address = <Spoke address from Section 2> // e.g. Main Spoke
// Step 1: get the Hub-internal asset ID
assetId = hub.getAssetId(USDC_ADDRESS)
// Step 2: convert to Spoke-specific reserveId
reserveId = spoke.getReserveId(hub_address, assetId)
// Now use reserveId in supply()/withdraw()
spoke.supply(reserveId, amount, user)
Note: reserveId values are per-Spoke — the same underlying asset can have different reserveId values across different Spokes. Always look up the reserveId for the specific Spoke you intend to interact with.
| Function | Returns | Description |
|----------|---------|-------------|
| getReserve(uint256 reserveId) | Reserve struct | Full reserve details: underlying address, hub, assetId, decimals, collateralRisk, flags |
| getReserveCount() | uint256 | Total number of reserves in the Spoke |
| getReserveConfig(uint256 reserveId) | ReserveConfig | Collateral risk parameters, paused/frozen status |
Endpoint: https://api.v4.aave.com/graphql
query {
reserves {
chain { name chainId }
asset { underlying { symbol address } }
summary { supplyApy { normalized } borrowApy { normalized } }
canBorrow
canSupply
}
}
The supplyApy.normalized field returns the annualized supply rate as a decimal (e.g. 0.035 = 3.5% APY).
| Aspect | Aave V3 | Aave V4 |
|---------------------|--------------------------------------|-----------------------------------------|
| Architecture | Isolated Pool per chain | Hub-and-Spoke, shared Liquidity Hub |
| Entry point | Pool.supply(asset, ...) | Spoke.supply(reserveId, ...) |
| Reserve identifier | address asset | uint256 reserveId |
| Referral code | uint16 referralCode (pass 0) | Removed |
| Return values | None (supply) / uint256 (withdraw) | (uint256, uint256) tuple for both |
| Chains | 10+ chains | Ethereum only (as of 2026-04) |
| Liquidity sharing | None — isolated per deployment | Cross-Spoke via shared Hub |
| Native ETH gateway | WrappedTokenGatewayV3 | Native Token Gateway |
Spark is a DeFi platform within the Sky (formerly MakerDAO) ecosystem, comprising two product lines:
Savings products span 6 chains; SparkLend is deployed only on Ethereum and Gnosis.
Supported chains:
| Chain | chainId | Savings | SparkLend | |-----------|---------|---------|-----------| | Ethereum | 1 | Yes | Yes | | Base | 8453 | Yes | No | | Arbitrum | 42161 | Yes | No | | Optimism | 10 | Yes | No | | Unichain | 130 | Yes | No | | Gnosis | 100 | Yes | Yes |
Product categories:
Only USDC / USDT / ETH / BTC related vaults are listed below.
| Chain | Vault Address | Underlying (USDC) |
|-----------|----------------------------------------------|----------------------------------------------|
| Ethereum | 0x28B3a8fb53B741A8Fd78c0fb9A6B2393d896a43d | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 |
| Avalanche | 0x28B3a8fb53B741A8Fd78c0fb9A6B2393d896a43d | 0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E |
Note: Avalanche has spUSDC in the address registry. Base / Arbitrum / Optimism / Unichain have a different savings product (sUSDC) that is a USDS-backed wrapper, not a direct USDC vault.
| Chain | Vault Address | Underlying (USDC) |
|-----------|----------------------------------------------|----------------------------------------------|
| Base | 0x3128a0F7f0ea68E7B7c9B00AFa7E41045828e858 | 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913 |
| Arbitrum | 0x940098b108fB7D0a7E374f6eDED7760787464609 | 0xaf88d065e77c8cC2239327C5EDb3A432268e5831 |
| Optimism | 0xCF9326e24EBfFBEF22ce1050007A43A3c0B6DB55 | 0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85 |
| Unichain | 0x14d9143BEcC348920b68D123687045db49a016C6 | 0x078D782b760474a361dDA0AF3839290b0EF57AD6 |
| Chain | Vault Address | Underlying (USDT) |
|-----------|----------------------------------------------|----------------------------------------------|
| Ethereum | 0xe2e7a17dFf93280dec073C995595155283e3C372 | 0xdAC17F958D2ee523a2206206994597C13D831ec7 |
| Chain | Vault Address | Underlying (WETH) |
|-----------|----------------------------------------------|----------------------------------------------|
| Ethereum | 0xfE6eb3b609a7C8352A241f7F3A21CEA4e9209B8f | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 |
No Spark Savings vault exists for BTC.
All Spark Savings vaults (spUSDC, spUSDT, spETH, sUSDC) implement the standard ERC-4626 interface.
// Returns the address of the underlying ERC-20 asset
function asset() external view returns (address);
// Total amount of the underlying asset managed by the vault
function totalAssets() external view returns (uint256);
// Vault share balance of `account`
function balanceOf(address account) external view returns (uint256);
// Convert `shares` to asset amount (no fees, no slippage)
function convertToAssets(uint256 shares) external view returns (uint256);
// Convert `assets` to share amount (no fees, no slippage)
function convertToShares(uint256 assets) external view returns (uint256);
// Preview how many shares a deposit of `assets` would yield
function previewDeposit(uint256 assets) external view returns (uint256);
// Preview how many assets a redeem of `shares` would yield
function previewRedeem(uint256 shares) external view returns (uint256);
// Deposit `assets` of underlying token, mint shares to `receiver`
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
// Withdraw exactly `assets`, burning shares from `owner`, sending assets to `receiver`
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
// Redeem exactly `shares`, sending resulting assets to `receiver` (preferred for full withdrawal)
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
// Approve the vault to spend underlying tokens on behalf of msg.sender
IERC20(underlying).approve(vaultAddress, amount);
1. Query underlying token address:
underlying = vault.asset()
2. Check user balance:
balance_raw = IERC20(underlying).balanceOf(user)
3. Approve vault to spend underlying:
IERC20(underlying).approve(vault_address, amount_raw)
4. Preview expected shares:
expected_shares = vault.previewDeposit(amount_raw)
5. Execute deposit:
shares = vault.deposit(amount_raw, receiver)
redeem)Using redeem is preferred over withdraw because it operates on shares (which the user holds) rather than a specific asset amount, avoiding rounding issues.
1. Check user share balance:
shares = vault.balanceOf(user)
2. Preview expected assets:
expected_assets = vault.previewRedeem(shares)
3. Execute redeem:
assets = vault.redeem(shares, receiver, owner)
vault.redeem(vault.balanceOf(user), user, user)
SparkLend is an Aave V3 fork deployed only on Ethereum and Gnosis.
| Chain | chainId | Pool Address | WETH Gateway |
|----------|---------|----------------------------------------------|----------------------------------------------|
| Ethereum | 1 | 0xC13e21B648A5Ee794902342038FF3aDAB66BE987 | 0xBD7D6a9ad7865463DE44B05F04559f65e3B11704 |
| Gnosis | 100 | 0x2Dae5307c5E3FD1CF5A72Cb6F698f915860607e0 | 0xBD7D6a9ad7865463DE44B05F04559f65e3B11704 |
| Asset | Underlying | spToken |
|-------|----------------------------------------------|----------------------------------------------|
| USDC | 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 | 0x377C3bd93f2a2984E1E7bE6A5C22c525eD4A4815 |
| USDT | 0xdAC17F958D2ee523a2206206994597C13D831ec7 | 0xe7dF13b8e3d6740fe17CBE928C7334243d86c92f |
| WETH | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 | 0x59cD1C87501baa753d0B5B5Ab5D8416A45cD71DB |
| WBTC | 0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599 | 0x4197ba364AE6698015AE5c1468f54087602715b2 |
| Asset | Underlying | spToken |
|-------|----------------------------------------------|----------------------------------------------|
| USDC | 0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83 | 0x5850D127a04ed0B4F1FCDFb051b3409FB9Fe6B90 |
| USDT | 0x4ECaBa5870353805a9F068101A40E0f32ed605C6 | 0x08B0cAebE352c3613302774Cd9B82D08afd7bDC4 |
| WETH | 0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1 | 0x629D562E92fED431122e865Cc650Bc6bdE6B96b0 |
Note: Gnosis does not have a WBTC reserve.
SparkLend uses the same interface as Aave V3 (it is an Aave V3 fork).
// Returns reserve data including aToken address, liquidity index, current rates
function getReserveData(address asset) external view returns (DataTypes.ReserveData memory);
// Returns user account data (total collateral, total debt, available borrows, etc.)
function getUserAccountData(address user) external view returns (
uint256 totalCollateralBase,
uint256 totalDebtBase,
uint256 availableBorrowsBase,
uint256 currentLiquidationThreshold,
uint256 ltv,
uint256 healthFactor
);
// Supply `amount` of `asset` on behalf of `onBehalfOf`; referralCode is currently inactive (pass 0)
function supply(address asset, uint256 amount, address onBehalfOf, uint16 referralCode) external;
// Supply with ERC-2612 permit (single tx approve + supply)
function supplyWithPermit(
address asset, uint256 amount, address onBehalfOf, uint16 referralCode,
uint256 deadline, uint8 permitV, bytes32 permitR, bytes32 permitS
) external;
// Withdraw `amount` of `asset` to `to`; pass type(uint256).max for full withdrawal
function withdraw(address asset, uint256 amount, address to) external returns (uint256);
// Approve the Pool to spend underlying tokens on behalf of msg.sender
IERC20(underlying).approve(poolAddress, amount);
1. Check user balance:
balance_raw = IERC20(underlying).balanceOf(user)
2. Approve Pool to spend underlying:
IERC20(underlying).approve(pool_address, amount_raw)
3. Execute supply:
pool.supply(underlying, amount_raw, user, 0)
// referralCode = 0 (inactive)
1. Check user spToken balance:
sp_balance = IERC20(spToken).balanceOf(user)
2. Execute withdraw:
pool.withdraw(underlying, amount_raw, user)
pool.withdraw(underlying, type(uint256).max, user)
For native ETH deposits/withdrawals, use the WETH Gateway contract instead of the Pool directly:
// Deposit native ETH
IWETHGateway(gateway).depositETH{value: amount}(pool_address, onBehalfOf, 0);
// Withdraw to native ETH (requires spWETH approval to gateway)
IWETHGateway(gateway).withdrawETH(pool_address, amount, to);
getReserveData() or The Graph subgraphconvertToAssets() method or SSR OracleAll contract addresses sourced from:
github.com/sparkdotfi/spark-address-registry (Ethereum.sol, Base.sol, Arbitrum.sol, Optimism.sol, Unichain.sol, Gnosis.sol)github.com/marsfoundation/sparklend-deployments (primary-latest.json for chain 1 and 100)Morpho V2 vaults are ERC-4626 standard tokenized vaults. Users deposit an underlying asset (e.g. USDC) and receive vault shares representing their proportional claim on the vault's total assets.
Supported chains:
| Chain | chainId | |----------|---------| | Ethereum | 1 | | Monad | 143 |
All vaults below are Morpho V2; V1 is excluded.
| Vault Name | Chain | Vault Address | Underlying | URL |
|--------------------------------|----------|----------------------------------------------|------------|-----|
| Steakhouse Reservoir USDC | Ethereum | 0xBEeFF047C03714965a54b671A37C18beF6b96210 | USDC | https://app.morpho.org/ethereum/vault/0xBEeFF047C03714965a54b671A37C18beF6b96210/steakhouse-reservoir-usdc |
| SkyMoney USDC Risk Capital | Ethereum | 0x56bfa6f53669B836D1E0Dfa5e99706b12c373ecf | USDC | https://app.morpho.org/ethereum/vault/0x56bfa6f53669B836D1E0Dfa5e99706b12c373ecf/skymoney-usdc-risk-capital |
| Re Ecosystem Vault | Ethereum | 0xD1E9242e075Db4bdd3f3c721D7d5fd4180A94A7e | USDC | https://app.morpho.org/ethereum/vault/0xD1E9242e075Db4bdd3f3c721D7d5fd4180A94A7e/re-ecosystem-vault |
| Vault Name | Chain | Vault Address | Underlying | URL |
|--------------------------------|----------|----------------------------------------------|------------|-----|
| SkyMoney USDT Savings | Ethereum | 0x23f5E9c35820f4baB695Ac1F19c203cC3f8e1e11 | USDT | https://app.morpho.org/ethereum/vault/0x23f5E9c35820f4baB695Ac1F19c203cC3f8e1e11/skymoney-usdt-savings |
| Steakhouse High Yield Instant | Ethereum | 0xbeeff07d991C04CD640DE9F15C08ba59c4FEDEb7 | USDT | https://app.morpho.org/ethereum/vault/0xbeeff07d991C04CD640DE9F15C08ba59c4FEDEb7/steakhouse-high-yield-instant |
| Steakhouse High Yield USDT0 | Monad | 0xbeeff300E9A9caeC7beEA740ab8758D33b777509 | USDT0 | https://app.morpho.org/monad/vault/0xbeeff300E9A9caeC7beEA740ab8758D33b777509/steakhouse-high-yield-usdt0 |
| Vault Name | Chain | Vault Address | Underlying | URL |
|--------------------------------|----------|----------------------------------------------|------------|-----|
| Steakhouse Prime ETH | Monad | 0xbeef04b01e0275D4ac2e2986256BB14E3Ff6ef42 | ETH | https://app.morpho.org/monad/vault/0xbeef04b01e0275D4ac2e2986256BB14E3Ff6ef42/steakhouse-prime-eth |
| Steakhouse Prime Instant | Ethereum | 0xbeef0046fcab1dE47E41fB75BB3dC4Dfc94108E3 | ETH | https://app.morpho.org/ethereum/vault/0xbeef0046fcab1dE47E41fB75BB3dC4Dfc94108E3/steakhouse-prime-instant |
| KPK ETH Prime V2 | Ethereum | 0xBb50A5341368751024ddf33385BA8cf61fE65FF9 | ETH | https://app.morpho.org/ethereum/vault/0xBb50A5341368751024ddf33385BA8cf61fE65FF9/kpk-eth-prime-v2 |
| Vault Name | Chain | Vault Address | Underlying | URL |
|--------------------------------|----------|----------------------------------------------|------------|-----|
| Hyperithm cbBTC Apex | Monad | 0xe09A93786275546690247d70f1767cF0b69e8Ea0 | cbBTC | https://app.morpho.org/monad/vault/0xe09A93786275546690247d70f1767cF0b69e8Ea0/hyperithm-cbbtc-apex |
All Morpho V2 vaults implement the ERC-4626 standard. Below are the core function signatures.
// Returns the address of the underlying ERC-20 asset
function asset() external view returns (address);
// Total amount of the underlying asset managed by the vault
function totalAssets() external view returns (uint256);
// Vault share balance of `account`
function balanceOf(address account) external view returns (uint256);
// Convert `shares` to asset amount (no fees, no slippage)
function convertToAssets(uint256 shares) external view returns (uint256);
// Convert `assets` to share amount (no fees, no slippage)
function convertToShares(uint256 assets) external view returns (uint256);
// Preview how many shares a deposit of `assets` would yield
function previewDeposit(uint256 assets) external view returns (uint256);
// Preview how many assets a redeem of `shares` would yield
function previewRedeem(uint256 shares) external view returns (uint256);
// Deposit `assets` of underlying token, mint shares to `receiver`
function deposit(uint256 assets, address receiver) external returns (uint256 shares);
// Withdraw exactly `assets`, burning shares from `owner`, sending assets to `receiver`
function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);
// Redeem exactly `shares`, sending resulting assets to `receiver` (preferred for full withdrawal)
function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);
// Approve the vault to spend underlying tokens on behalf of msg.sender
IERC20(underlying).approve(vaultAddress, amount);
1. Query underlying token address:
underlying = vault.asset()
2. Check user balance:
balance_raw = IERC20(underlying).balanceOf(user)
3. Approve vault to spend underlying:
IERC20(underlying).approve(vault_address, amount_raw)
4. Preview expected shares:
expected_shares = vault.previewDeposit(amount_raw)
5. Execute deposit:
shares = vault.deposit(amount_raw, receiver)
redeem)Using redeem is preferred over withdraw because it operates on shares (which the user holds) rather than a specific asset amount, avoiding rounding issues.
1. Check user share balance:
shares = vault.balanceOf(user)
2. Preview expected assets:
expected_assets = vault.previewRedeem(shares)
3. Execute redeem:
assets = vault.redeem(shares, receiver, owner)
vault.redeem(vault.balanceOf(user), user, user)
Endpoint: https://api.morpho.org/graphql
query {
vaultByAddress(address: "0xBEeFF047C03714965a54b671A37C18beF6b96210", chainId: 1) {
address
symbol
asset {
symbol
decimals
address
}
state {
totalAssets
apy
netApy
}
}
}
Use multiple vaultByAddress calls with GraphQL aliases:
query {
steakhouseUSDC: vaultByAddress(address: "0xBEeFF047C03714965a54b671A37C18beF6b96210", chainId: 1) {
address
symbol
state { apy netApy totalAssets }
}
skymoneyUSDC: vaultByAddress(address: "0x56bfa6f53669B836D1E0Dfa5e99706b12c373ecf", chainId: 1) {
address
symbol
state { apy netApy totalAssets }
}
# ... add remaining vaults
}
tools
TQX (tqx.trade) HK/US stock quant workflow via tqx-cli: cross-sectional factor analysis, event-driven strategy backtests on the panda_backtest engine, and agent-driven automated paper trading. Use when the user wants to run factor IC/IR analysis, backtest a Python trading strategy on Hong Kong or US stocks, or set up agent-automated trading (e.g. "backtest a moving-average strategy on AAPL", "analyze a momentum factor on HK stocks", "let the agent trade my paper account").
tools
中学物理实验教学参赛方案套件。包含四个完整实验(单摆测g、声悬浮测声速、向心力定量演示仪、电磁阻尼定量研究),每套含固件源码、3D打印图纸、教学PPT、教学文稿、采购清单、调试手册、视频分镜脚本、模拟器。Use when a teacher/student needs a complete, classroom-ready physics experiment package for competition or teaching.
development
End-to-end blog management for AI agents. Write, import, build, preview, and publish articles using the blog template. Covers draft workflow, article import, SEO, OG images, and deployment.
development
ESP8266/ESP32 + 磁簧开关/霍尔传感器 单摆测重力加速度实验套件。 硬件搭建→固件烧录→数据采集→Web仪表盘→g值计算→教学文档,一站式完成。 Use when the user wants to build a pendulum g-measurement experiment, measure gravity with a micro-controller, or needs a complete physics experiment package with hardware + firmware + dashboard + teaching materials.