Lending, vaults and earn
Supply, borrow and loop on lending markets, deposit in vaults, lock a fixed rate on Pendle, or let earn route an asset to the best rate, all from Flowscript.
Lending markets#
Aave, Spark, Compound, Kamino and marginfi share one surface:
| Read | Action |
|---|---|
<id>.supplyApy("chain:asset", interval) | <id>.supply({ asset, usd }) |
<id>.supplied(), <id>.borrowed() | <id>.withdraw({ asset, all: true }) |
<id>.healthFactor() | <id>.borrow({ asset, usd }), <id>.repay({ asset, all: true }) |
Sizes are units of the token, dollars at the protocol's price, a percent of what's there, or all. Aave and Spark also take E-mode and collateral switches, so a strategy can loop, roll a borrow or swap collateral. A move the protocol would refuse reverts with the contract's own reason.
Vaults#
Morpho, Euler, Yearn, Fluid, Gearbox, Sky, Ethena, Maple and others: <id>.apy(…), <id>.deposit, <id>.withdraw and <id>.deposited(). Euler, Yearn and Morpho also take any vault by its address (base:0x…), checked on chain when the strategy is saved.
Fixed rates on Pendle#
Buy a Pendle PT to lock its implied rate to maturity: pendle.impliedApy("ethereum:0x…", interval), pendle.buy, pendle.sell and pendle.held(). The classic pairing: hold the PT while its implied rate beats Aave's supply rate by a margin, and go back to Aave when the gap closes.
uses { pendle: "^1", aave: "^1" }
const fixed = pendle.impliedApy("ethereum:roll:siusd", interval);
const float = aave.supplyApy("ethereum:usdc", interval);
const spread = fixed - float;
metric("spread", spread);
when (spread > 3 && pendle.held("ethereum:roll:siusd") == 0) {
aave.withdraw({ asset: "ethereum:usdc", all: true });
pendle.buy({ asset: "ethereum:roll:siusd", all: true });
}
when (spread < 0.5 && pendle.held("ethereum:roll:siusd") > 0) {
pendle.sell({ asset: "ethereum:roll:siusd", all: true });
aave.supply({ asset: "ethereum:usdc", all: true });
}ethereum:roll:siusd follows the current Pendle market for an asset and rolls to the next one at maturity.
earn: the best rate for an asset#
earn routes an asset instead of naming a protocol. earn.apy("usdc", interval) is the best rate across live USDC markets; earn.deposit, earn.withdraw and earn.rebalance({ minGainPct, costUsd }) move it; earn.deposited() and earn.heldApy() read the book.
Give rebalance a minGainPct of a point or more and a costUsd of what one move costs, so it doesn't bridge back and forth on noise.
Reading the edge#
Each protocol has its own guide (in the module's page, or get_protocol_guide for an AI) saying where its edge is and what the paper book leaves out: reward tokens, withdrawal queues, cooldowns, oracle quirks. Read it before designing a strategy on it.