Aave V3 Integration
Comprehensive guide to securing Aave V3 positions with Matador.
Matador is highly effective for managing delegated access to Aave V3 positions. By defining granular policies, you can allow automated bots to manage health factors or rebalance portfolios without risking the principal collateral.
Security Architecture
Permission Patterns
1. Safe Lending (Supply & Withdraw)
The primary risk in lending is fund diversion: an attacker withdrawing your collateral to their own wallet.
import "abis/AavePool.json" as Aave;
permission SafeLending -> 1.0.0 {
parameters: {
authorizer: address,
pool: address,
account: address
}
pub fn authorize() -> bool {
return authorizedBy(parameters.authorizer);
}
fn main() -> bool {
if (context.target != parameters.pool) {
return false;
}
if (context.selector == Aave.supply) {
return Aave.supply.onBehalfOf == parameters.account;
} else if (context.selector == Aave.withdraw) {
return Aave.withdraw.to == parameters.account;
}
return false;
}
}2. Health Factor Guardian
Allow a bot to borrow assets, but only if the account is healthy when the policy is evaluated.
Aave health read
The policy reads Aave V3 getUserAccountData(...).healthFactor directly from the Pool ABI. It does not rely on a caller-supplied health-factor value.
import "abis/AavePool.json" as Aave;
permission ControlledBorrow -> 1.0.0 {
parameters: {
authorizer: address,
pool: Aave,
account: address,
borrowAmount: uint256,
minHealthFactor: uint256
}
pub fn authorize() -> bool {
return authorizedBy(parameters.authorizer);
}
fn main() -> bool {
if (context.target != parameters.pool) {
return false;
}
if (context.selector == Aave.borrow) {
if (Aave.borrow.onBehalfOf != parameters.account) {
return false;
}
if (Aave.borrow.amount != parameters.borrowAmount) {
return false;
}
let healthFactor = parameters.pool.getUserAccountData(parameters.account).healthFactor;
return healthFactor >= parameters.minHealthFactor;
}
return false;
}
}3. Emergency Repay (Panic Mode)
Create a "Panic Mode" policy that allows ANYONE (or a specific keeper) to repay debt if the health factor drops dangerously low, bypassing other restrictions.
import "abis/AavePool.json" as Aave;
permission EmergencyRepay -> 1.0.0 {
parameters: {
authorizer: address,
pool: address,
account: address
}
pub fn authorize() -> bool {
return authorizedBy(parameters.authorizer);
}
fn main() -> bool {
if (context.target != parameters.pool) {
return false;
}
if (context.selector == Aave.repay) {
return Aave.repay.onBehalfOf == parameters.account;
}
return false;
}
}Integration Tutorial
Setup Project
Install the CLI and download the Aave V3 ABI.
npm install -D @steerprotocol/matador-cli
mkdir abis
# Download Aave Pool ABI to ./abis/AavePool.jsonWrite the Policy
Create policies/aave-supply.matador.
import "abis/AavePool.json" as Aave;
permission AaveSupply -> 1.0.0 {
parameters: {
pool: address,
account: address
}
fn main() -> bool {
if (context.target != parameters.pool) {
return false;
}
if (context.selector == Aave.supply) {
return Aave.supply.onBehalfOf == parameters.account;
}
return false;
}
}Compile
Compile the policy to bytecode.
npx --package @steerprotocol/matador-cli matador-policy-cli compile policies/aave-supply.matadorDeploy
Grant the permission to your smart account.
const policy = require('./policies/aave-supply.json');
// Grant permission on-chain...Gas Optimization
Aave interactions are gas-intensive. Minimize overhead by:
- Checking Selectors First:
context.selector == Aave.supplyis cheap (4 bytes comparison). Do this before complex logic. - Avoid Redundant State Checks: If you trust the bot, you might skip the on-chain
getUserAccountDatacheck for every single supply transaction, reserving it only for borrows.
Troubleshooting
| Issue | Cause | Fix |
|---|---|---|
PermissionViolation | onBehalfOf mismatch. | Ensure the bot is supplying on behalf of the smart account, not itself. |
Call Reverted | Aave Pool paused or frozen. | Check Aave protocol status. Matador cannot bypass protocol-level pauses. |
Invalid ABI | Mismatch between V2 and V3 ABIs. | Ensure you are using the V3 Pool ABI. V2 uses LendingPool. |