Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

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-keeper for the other side)

Generate it

rflow new --template aave-health-guardian
 
# or add the workflow to an existing project
rflow add workflow aave-health-guardian

Non-interactive (CI/agents):

rflow new --template aave-health-guardian --yes --output ./guardian \
  --answer min_health=1.05 --answer repay_amount=1000

Inputs

keytypedefault
project_namestringaave-health-guardian
network / chain_id / rpc_env / rpc_urlnetwork / chain_id / env_var / stringethereum / 1 / ETH_RPC / a public RPC
confirmationsint3
pool_name / pool_addresscontract / addressPool / zero placeholder (replace!)
debt_name / debt_asset_address / debt_decimalscontract / address / intDebtAsset / USDC mainnet / 6
positionaddresszero placeholder (replace!)
min_health / health_decimalstoken_amount / int1.05 / 18
repay_amount / rate_modetoken_amount / int1000 / 2
poll_every / approval_timeoutduration30s / 15m
gas_max_pricestring60 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 start

Common modifications

  • swap repay for supply (add collateral) โ€” same shape, different function
  • lower poll_every and widen min_health for tighter guarding
  • pre-approve the Pool once and drop the approve step