Aave v3 health guardian
Template: aave-health-guardian ยท category: keeper ยท risk: money_moving
Guards an Aave v3 position from your own side. It polls
getUserAccountData(position).healthFactor; when it drops below a floor, it
approves the Pool for the debt asset and parks a repay behind a human
approval to restore health. A position with no debt reports healthFactor = uint256 max, so it never trips.
When to use it
- keep a leveraged position off the liquidation line automatically
- want a human to confirm each repay, with the live health factor in the message
- self-protect rather than liquidate others (see
liquidation-keeperfor the other side)
Generate it
rflow new --template aave-health-guardian
# or add the workflow to an existing project
rflow add workflow aave-health-guardianNon-interactive (CI/agents):
rflow new --template aave-health-guardian --yes --output ./guardian \
--answer min_health=1.05 --answer repay_amount=1000Inputs
| key | type | default |
|---|---|---|
project_name | string | aave-health-guardian |
network / chain_id / rpc_env / rpc_url | network / chain_id / env_var / string | ethereum / 1 / ETH_RPC / a public RPC |
confirmations | int | 3 |
pool_name / pool_address | contract / address | Pool / zero placeholder (replace!) |
debt_name / debt_asset_address / debt_decimals | contract / address / int | DebtAsset / USDC mainnet / 6 |
position | address | zero placeholder (replace!) |
min_health / health_decimals | token_amount / int | 1.05 / 18 |
repay_amount / rate_mode | token_amount / int | 1000 / 2 |
poll_every / approval_timeout | duration | 30s / 15m |
gas_max_price | string | 60 gwei |
Required env vars
DATABASE_URL, the RPC env var (default ETH_RPC), and
RAW_DANGEROUS_MNEMONIC โ rflow new writes a fresh DEV-ONLY mnemonic;
swap in a production signer before real funds ride on it.
Safety notes
Money-moving, so every rail is on: pre-flight simulation with
assert_sim: ["${{ sim.ok }}"] on both the approve and the repay, a
gas.max_price ceiling, a concurrency group (skip), wait_for: confirmed
and on_failure: dead_letter. The repay is parked behind
approval โ rflow approve <id> โ and re-simulates immediately
before broadcast. The health test is edge-triggered, so a position sitting
under the floor does not re-fire every poll. Attach a
budget to cap cumulative repay spend.
Run it locally
docker compose up -d # postgres on localhost:5448
# fill .env (RPC + a real signer), set pool/debt/position
rflow validate
rflow startCommon modifications
- swap
repayforsupply(add collateral) โ same shape, different function - lower
poll_everyand widenmin_healthfor tighter guarding - pre-approve the Pool once and drop the
approvestep