This skill should be used when the user asks about "risk premium", "collateral risk", "user risk premium", "premium debt", "premium shares", "collateral quality", or needs to understand Aave V4's risk-based interest system.
Calculates personalized borrowing rates based on collateral quality and risk in Aave V4.
npx claudepluginhub cyotee/aave-v4-skillThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Aave V4 introduces a sophisticated Risk Premium system where borrowing costs depend on the quality of collateral used. Higher-quality collateral (like ETH) gets lower rates, while riskier collateral pays more.
┌──────────────────────────────────────────────────────────────┐
│ RISK PREMIUM │
├──────────────────────────────────────────────────────────────┤
│ │
│ Interest Rate = Base Rate × (1 + User Risk Premium) │
│ │
│ Example: │
│ Base Rate = 5% │
│ Risk Premium = 20% (0.20) │
│ User Rate = 5% × 1.20 = 6% │
│ │
│ Collateral Quality Spectrum: │
│ ┌────────────────────────────────────────────────────────┐ │
│ │ ETH (CR=0) ─────────────────────────── SHITCOIN (CR=1000_00)│
│ │ Low Risk High Risk │ │
│ │ Low Premium High Premium │ │
│ └────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────┘
Each asset has a Collateral Risk value (0 to 1000_00 BPS):
// Collateral Risk is per-reserve, per-Spoke
struct Reserve {
// ...
uint24 collateralRisk; // 0 = highest quality, 1000_00 = lowest quality
}
// Examples:
// ETH: CR = 0 (risk-free reference)
// wstETH: CR = 5_00 (0.05% - very low risk)
// WBTC: CR = 10_00 (0.10% - low risk)
// USDC: CR = 0 (stablecoin - no risk premium)
// LINK: CR = 50_00 (0.50% - moderate risk)
// NewToken: CR = 200_00 (2.00% - higher risk)
The User Risk Premium is a weighted average of Collateral Risk across the user's collateral:
RP_u = Σ(CR_i × CollateralValue_i) / Σ(CollateralValue_i)
Where the sum only includes enough collateral to cover the user's debt (sorted by risk, lowest first).
/// @notice Calculate user's risk premium
/// @dev Covers debt with lowest-risk collateral first
function _calculateUserRiskPremium(address user) internal view returns (uint24) {
PositionStatus storage status = _positionStatus[user];
// Get total debt value
uint256 totalDebtValue = _getTotalDebtValue(user);
if (totalDebtValue == 0) return 0;
// Sort collateral by Collateral Risk (ascending)
CollateralInfo[] memory collaterals = _getCollateralsSortedByRisk(user);
// Iterate and cover debt with lowest-risk collateral first
uint256 coveredDebt = 0;
uint256 weightedRiskSum = 0;
uint256 weightedValueSum = 0;
for (uint256 i = 0; i < collaterals.length; i++) {
uint256 remainingDebt = totalDebtValue - coveredDebt;
if (remainingDebt == 0) break;
uint256 collateralValue = collaterals[i].value;
uint24 collateralRisk = collaterals[i].risk;
if (remainingDebt >= collateralValue) {
// Use full collateral
weightedRiskSum += uint256(collateralRisk) * collateralValue;
weightedValueSum += collateralValue;
coveredDebt += collateralValue;
} else {
// Use partial collateral (just enough to cover debt)
weightedRiskSum += uint256(collateralRisk) * remainingDebt;
weightedValueSum += remainingDebt;
coveredDebt += remainingDebt;
}
}
// Calculate weighted average
return uint24(weightedRiskSum / weightedValueSum);
}
User Position:
- Debt: $10,000 USDC
- Collateral:
- $8,000 ETH (CR = 0)
- $5,000 LINK (CR = 50_00)
- $3,000 NewToken (CR = 200_00)
Step 1: Sort by CR (ascending): ETH, LINK, NewToken
Step 2: Cover $10,000 debt:
- Use $8,000 ETH (covers $8,000)
- Use $2,000 LINK (covers remaining $2,000)
Step 3: Calculate weighted average:
RP = (0 × $8,000 + 50_00 × $2,000) / $10,000
RP = 100_000 / 10,000
RP = 10_00 (0.10%)
User's borrow rate = Base Rate × (1 + 0.10%)
V4 tracks premium debt separately from base debt using shares and offsets:
// In Hub (Asset-level)
struct Asset {
uint256 premiumShares; // Total premium shares across all Spokes
uint256 premiumOffsetRay; // Total premium offset (RAY)
}
// In Spoke (User-level)
struct UserPosition {
uint256 premiumSharesRay; // User's premium shares (RAY precision)
uint256 premiumOffsetRay; // User's premium offset (RAY)
}
At borrow time, premium shares are created with an offset that makes initial premium debt = 0:
// When borrowing:
function _addPremiumShares(
UserPosition storage position,
uint256 drawnShares,
uint256 riskPremium
) internal {
// Calculate premium shares = drawn shares × risk premium
uint256 newPremiumShares = drawnShares.rayMul(riskPremium);
// Get current premium share value in assets
uint256 premiumAssetValue = _getPremiumAssetValue(newPremiumShares);
// Set offset equal to asset value (so premium debt starts at 0)
position.premiumSharesRay += newPremiumShares;
position.premiumOffsetRay += premiumAssetValue;
}
Premium Debt = Premium Shares Value - Premium Offset
At borrow time:
Premium Shares Value = X
Premium Offset = X
Premium Debt = X - X = 0
After time passes (interest accrues):
Premium Shares Value = X × (1 + interest)
Premium Offset = X (unchanged)
Premium Debt = X × (1 + interest) - X = X × interest
When repaying or refreshing premium, a PremiumDelta is used:
struct PremiumDelta {
int256 sharesDelta; // Change in premium shares
int256 offsetRayDelta; // Change in premium offset (RAY)
uint256 restoredPremiumRay; // Premium amount being repaid (RAY)
}
// Example: Full premium repayment
PremiumDelta memory delta = PremiumDelta({
sharesDelta: -int256(position.premiumSharesRay),
offsetRayDelta: -int256(position.premiumOffsetRay),
restoredPremiumRay: premiumDebt.rayMul(WadRayMath.RAY)
});
The User Risk Premium is recalculated when:
updateUserRiskPremium()For gas efficiency, V4 uses lazy updates - the RP isn't continuously updated:
/// @notice Permissionlessly update user's risk premium
function updateUserRiskPremium(address user) external {
uint24 newRiskPremium = _calculateUserRiskPremium(user);
// Refresh premium shares with new risk premium
_refreshUserPremium(user, newRiskPremium);
emit UpdateUserRiskPremium(user, newRiskPremium);
}
Governance can force-update a user's risk premium:
/// @notice Governor can force update user's risk premium
function forceUpdateUserRiskPremium(address user) external restricted {
uint24 newRiskPremium = _calculateUserRiskPremium(user);
_refreshUserPremium(user, newRiskPremium);
}
User Borrow Rate = Base Rate × (1 + Risk Premium)
Where:
- Base Rate = f(utilization) [from Hub interest rate strategy]
- Risk Premium = User-specific based on collateral quality
// Total Debt = Drawn Debt + Premium Debt
// Drawn Debt = principal + base interest
uint256 drawnDebt = position.drawnShares.rayMul(hub.getDrawnIndex());
// Premium Debt = risk premium interest
uint256 premiumDebt = position.premiumSharesRay.rayMul(hub.getDrawnIndex()) - position.premiumOffsetRay;
uint256 totalDebt = drawnDebt + premiumDebt;
struct ReserveConfig {
uint24 collateralRisk; // 0-1000_00 BPS
// ... other fields
}
function updateReserveConfig(
uint256 reserveId,
ReserveConfig calldata config
) external restricted {
Reserve storage reserve = _getReserve(reserveId);
reserve.collateralRisk = config.collateralRisk;
// ...
}
// Hub can set a max risk premium threshold
uint24 public constant MAX_RISK_PREMIUM_THRESHOLD = type(uint24).max;
// Used in validation
function _validateRiskPremium(uint24 riskPremium) internal view {
require(riskPremium <= MAX_RISK_PREMIUM_THRESHOLD, ExcessiveRiskPremium());
}
┌──────────────────────────────────────────────────────────────┐
│ RISK PREMIUM BENEFITS │
├──────────────────────────────────────────────────────────────┤
│ │
│ For Protocol: │
│ • Accurately prices risk │
│ • Attracts higher-quality collateral │
│ • Reduces systemic risk │
│ │
│ For Suppliers: │
│ • Higher yields from risky collateral borrowers │
│ │
│ For Borrowers with Good Collateral: │
│ • Lower borrowing costs │
│ • Incentive to use ETH/stables as collateral │
│ │
│ For Borrowers with Risky Collateral: │
│ • Fair pricing for risk taken │
│ • Still able to borrow (at higher cost) │
│ │
└──────────────────────────────────────────────────────────────┘
event UpdateUserRiskPremium(address indexed user, uint24 riskPremium);
event UpdateReserveCollateralRisk(uint256 indexed reserveId, uint24 collateralRisk);
src/spoke/Spoke.sol - Risk premium calculationssrc/hub/Hub.sol - Premium share accountingsrc/hub/libraries/Premium.sol - Premium math utilitiessrc/spoke/libraries/UserPositionDebt.sol - User debt calculationsdocs/overview.md - Risk premium algorithmActivates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins.