> ## Documentation Index
> Fetch the complete documentation index at: https://docs.eco.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Repay Aave V3 debt when the health factor is below a target

> One Base or Ethereum transaction that reads the Pot's Aave V3 health factor and, below a target, repays the Pot's USDC debt from its USDC.

The program reads the Pot's health factor from `AaveV3.Pool.getUserAccountData`. Below `target`, it repays the Pot's variable-rate USDC debt with `maxRepay` USDC, or with what the Pot holds if that is less, and returns the health factor before and after. At or above `target`, it moves nothing. The cook reverts if `target` is not above 1.0, if the Pot holds no USDC when a repayment is due, or if Aave refuses the repayment.

**Target chains:** Base and Ethereum. Both registries include `USDC` and `AaveV3.Pool`. The recorded Base simulation exercises only the branch that skips repayment.

## Prerequisites

You need the `sauce` command (`npm install -g @eco-incorp/sauce`) and, to send, a wallet (`sauce wallet new`) holding the USDC for the Pot and the gas. See [Installation](https://docs.eco.com/sauce-sdk/installation.md).

## Program

`pot` is the Pot the program runs on, available without declaring it ([Names](https://docs.eco.com/sauce/names.md#balances)).

```ts aave-repay-by-health.sauce.ts theme={null}
// Reads the Pot's Aave V3 health factor. Below `target`, it repays the Pot's variable-rate USDC
// debt from the Pot's USDC: `maxRepay`, or what the Pot holds if that is less. What Aave pulled is
// measured as the change in the Pot's USDC, and an allowance left over is set back to zero. At or
// above `target`, it does nothing. The cook reverts when the Pot holds no USDC to repay with or
// Aave refuses the repayment.
//
//   sauce simulate aave-repay-by-health.sauce.ts --chain <chain> --owner <address> \
//     --args <target> <maxRepay>
//   sauce run aave-repay-by-health.sauce.ts --chain <chain> --wallet <name> \
//     --fund USDC:<maxRepay>n --args <target> <maxRepay>
//
//   target: Uint256    repay below this health factor, as Aave states it (times 1e18):
//                      1500000000000000000 is 1.5
//   maxRepay: Uint256  the most USDC to repay, in USDC's base units (6 decimals):
//                      500000000 is 500 USDC
//
// On Base, repay up to 500 USDC when the health factor is below 1.5:
//
//   sauce run aave-repay-by-health.sauce.ts --chain base --wallet me \
//     --args 1500000000000000000 500000000

function main(
  target: Uint256,
  maxRepay: Uint256,
): { before: Uint256; after: Uint256; repaid: Uint256 } {
  require(target > 1000000000000000000, "target must be above 1.0");

  const before = AaveV3.Pool.getUserAccountData(pot).healthFactor;
  if (before >= target) {
    return { before, after: before, repaid: 0 };
  }

  const held = pot.USDC;
  const amount = maxRepay < held ? maxRepay : held;
  require(amount > 0, "no USDC in the Pot to repay with");

  USDC.approve(AaveV3.Pool, amount);
  AaveV3.Pool.repay(USDC, amount, 2, pot);
  const repaid = held - pot.USDC;
  if (repaid < amount) {
    // Aave pulled less than the approval: clear the rest of the allowance.
    USDC.approve(AaveV3.Pool, 0);
  }

  const after = AaveV3.Pool.getUserAccountData(pot).healthFactor;
  return { before, after, repaid };
}
```

## How it works

* The registry's `AaveV3.Pool` declares no read of the Pot's USDC debt or of Aave's prices, so the program does not compute the repayment that restores `target`. It repays a fixed amount, capped by `maxRepay` and by the Pot's USDC, and `after` reports where the health factor landed.
* `repay`'s result is discarded, and a discarded result is neither decoded nor checked, so `repaid` is the change in the Pot's USDC. When Aave pulled less than the approved amount, the program sets the Pot's allowance to `AaveV3.Pool` back to zero, so no allowance outlives the cook.
* `repay` takes interest rate mode `2` (variable) and `pot` as `onBehalfOf`, so it repays only the Pot's own position.

## Run the example

**1. Compile**

```bash theme={null}
sauce compile aave-repay-by-health.sauce.ts --chain base
sauce compile aave-repay-by-health.sauce.ts --chain ethereum
```

**2. Simulate**

```bash theme={null}
sauce simulate aave-repay-by-health.sauce.ts --chain base --owner <your-address> \
  --assume-balance USDC:500 --args 1500000000000000000 500000000
```

`--assume-balance USDC:500` gives the Pot 500 USDC for this simulation only. The result lists the health factor before and after and the USDC repaid.

**3. Send**

```bash theme={null}
sauce run aave-repay-by-health.sauce.ts --chain base --wallet <name> \
  --fund USDC:500 --args 1500000000000000000 500000000
```

`--fund USDC:500` pulls 500 USDC from your wallet into the Pot in the same cook; leave it out when the Pot already holds the USDC. `sauce tx` prints the unsigned transactions instead, for your own signer: the Pot's deployment if it has no code yet, the transfer of the USDC into the Pot (with `--fund`), then the cook.

```bash theme={null}
sauce tx aave-repay-by-health.sauce.ts --chain base --owner <your-address> \
  --fund USDC:500 --args 1500000000000000000 500000000
```

## Simulation result

Simulated on a local fork of Base at block 52965104 with the current contracts, with the command above. Nothing was signed or sent.

```text theme={null}
main returns { before: Uint256, after: Uint256, repaid: Uint256 }: { before: 115792089237316195423570985008687907853269984665640564039457584007913129639935, after: 115792089237316195423570985008687907853269984665640564039457584007913129639935, repaid: 0 }
...
Assumed for this simulation only, by state override:
  the Pot holds 500 USDC: --assume-balance (its balance word 0xcb5320fe60abad81834e0e994e8a7a8eb33991917b05a5c0498fe1c0373a2087: Solidity mapping at slot 9)
...
```

The Pot is deployed inside the simulation and has no Aave position, so `getUserAccountData` reports the largest `uint256` as its health factor. That is at or above any `target`, so the program returned at once with `repaid: 0`; no USDC moved, and the only moves in the output are the cook's value and the Kitchen's fee. The cook used 88,867 gas.

Not simulated: the repay branch. It runs only when the Pot has USDC debt on Aave V3 and a health factor below `target`. The Pot in this simulation was deployed inside the simulation and has no Aave position; `--assume-balance` sets token balances, not Aave debt. The compile output for Base, from `sauce compile aave-repay-by-health.sauce.ts --chain base --json`:

```text theme={null}
  "chain": "base",
...
  "size": 728,
```

## Next steps

* [Borrow with a health-factor floor](https://docs.eco.com/quickstarts/sauce/aave-borrow-guard.md): opens the kind of position this program repays, with a minimum health factor.
* [Supply idle USDC](https://docs.eco.com/quickstarts/sauce/supply-idle.md): keeps a USDC reserve in the Pot and supplies the rest to Aave V3.
* [`sauce simulate`](https://docs.eco.com/sauce-sdk/cli/simulate), [Pot](https://docs.eco.com/sauce/pot.md), [Protocols reference](https://docs.eco.com/sauce-sdk/reference/protocols.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.