Borrow Assets

Learn how to borrow assets from Aave v4 reserves against your collateral.


Borrowing assets from Aave v4 allows you to:

  • Access liquidity without selling your assets

  • Leverage your positions with borrowed capital

  • Repay borrowed assets at any time to close your position

Borrowing assets creates a debt that reduces the position's health factor. Make sure to maintain sufficient collateralization to avoid liquidation. Monitor the position's health factor regularly and consider market volatility.

Borrowing

Borrowing on Aave v4 takes place at the spoke level, and users can only borrow against collateral supplied to that same spoke.

Borrowing can be broken down into the following steps:

  1. Identify the Reserve to borrow from

  2. Preview the impact of the borrow operation

  3. Borrow the assets

Identify the Reserve

The first step is to filter the borrow reserves on the same spoke as the collateral to those marked with canBorrow: true.

Reserves List
const reserves: Reserve[] = [  {    id: "SGVsbG8h",    onChainId: "42",    canBorrow: true,    borrowCap: "1000000000.000000", // 1B USDC    status: {      frozen: false,      paused: false,    },    spoke: {      address: "0x123…",      // …    },    // …  },  {    id: "V29ybGQh",    onChainId: "43",    canBorrow: false, // cannot borrow from this reserve    borrowCap: "500000000.000000", // 500M DAI    status: {      frozen: true, // reserve is frozen      paused: false,    },    spoke: {      address: "0x123…",      // …    },    // …  },  // …];

The canBorrow flag confirms that the reserve is active: it isn’t frozen, it isn’t paused, and the borrow cap has not been reached.

From the remaining borrowable reserves, select the one that:

  • Best matches the desired token with a sufficient borrowable amount — this already accounts for the combined collateral factors (LTV ratios) of the position's collateral

  • Offers the lowest borrow APY — the effective borrow APY combines the reserve’s borrow APY with the Risk Premium tied to the position's collateral

Reserve
const reserve: Reserve = {  id: "SGVsbG8h",  onChainId: "42",  canBorrow: true,  chain: {    chainId: 1,    name: "Ethereum",  },  spoke: {    address: "0x123…",    // …  },  asset: {    underlying: {      address: "0xa0b86a33e6e2ad05ad6c9ac3b6e5e5f6e7b6c1b2", // USDC    },    // …  },  userState: {    borrowApy: {      normalized: "3.73", // 3.73% APY      // …    },    borrowable: {      amount: {        value: "10000.000000", // 10,000 USDC      },      // …    },    // …  },};

Make sure you include a user address when fetching reserve data—otherwise userState will be null.

Preview Borrow

Preview the impact of a borrow operation before committing to it.

Use the usePreview hook (or the imperative usePreviewAction variant) to preview the impact of the borrow operation on the user's position.

import { type BorrowRequest, usePreview } from "@aave/react";
function BorrowPreview({ request }: { request: BorrowRequest }) {  const { data, error, loading } = usePreview({    action: {      borrow: request,    },  });
  if (loading) return <div>Loading…</div>;  if (error) return <div>Error: {error.message}</div>;
  // data: PreviewUserPosition  return (    <div>      <h3>Health Factor:</h3>      <p>From: {data.healthFactor?.current ?? "N/A"}</p>      <p>To: {data.healthFactor?.after ?? "N/A"}</p>
      <h3>Risk Premium:</h3>      <p>From: {data.riskPremium.current.value}</p>      <p>To: {data.riskPremium.after.value}</p>
      <h3>Net APY:</h3>      <p>From: {data.netApy.current.value}</p>      <p>To: {data.netApy.after.value}</p>
      <h3>Net Collateral:</h3>      <p>From: {data.netCollateral.current.value}</p>      <p>To: {data.netCollateral.after.value}</p>    </div>  );}

Where the BorrowRequest can be as follows:

Borrow ERC-20
const request: BorrowRequest = {  sender: evmAddress("0x789…"), // User's address  reserve: reserve.id,  amount: {    erc20: {      value: bigDecimal(1000), // 1000 USDC    },  },};

You can also specify a different currency to return fiat amounts in.

import { Currency } from "@aave/react";
const { data, error, loading } = usePreview({  action: {    borrow: request,  },  currency: Currency.Eur,});

The PreviewUserPosition shows the impact of the borrow operation by comparing current and after states, with the table below outlining key fields and how to interpret them.

Current → AfterImpact
healthFactor?.current → healthFactor?.after: BigDecimalHigher is better
riskPremium.current → riskPremium.after: PercentNumberLower is better
netApy.current → netApy.after: PercentNumberHigher is better
netCollateral.current → netCollateral.after: FiatAmountHigher is better
netBalance.current → netBalance.after: FiatAmountUpdated balance

Step-by-Step

Now that we know how to identify a reserve to borrow from, and we know how to preview the impact of a borrow operation, let's see how to borrow assets from this reserve.

To borrow assets from an Aave reserve with AaveKit React, follow these steps.

1

Configure Wallet Integration

First, instantiate the useSendTransaction hook for the wallet library of your choice.

Viem
import { useWalletClient } from "wagmi";import { useSendTransaction } from "@aave/react/viem";
// …
const { data: wallet } = useWalletClient();const [sendTransaction] = useSendTransaction(wallet);

2

Define the Borrow Flow

Then, use the useBorrow hook to prepare the borrow operation.

import { useBorrow } from "@aave/react";
const [borrow, { loading, error }] = useBorrow((plan) => {  switch (plan.__typename) {    case "TransactionRequest":      return sendTransaction(plan);    case "Erc20ApprovalRequired":    case "PreContractActionRequired":      return sendTransaction(plan.transaction);  }});

3

Execute the Borrow Operation

Then, execute the desired borrow operation.

Borrow ERC-20
import { bigDecimal, evmAddress } from "@aave/react";
const execute = async () => {  const result = await borrow({    sender: evmAddress(wallet.account.address), // User's address    reserve: reserve.id,    amount: {      erc20: {        value: bigDecimal(100), // 100 USDC      },    },  });
  // …};

4

Handle the Result

Finally, handle the result.

Example
const execute = async () => {  const result = await borrow(/* … */);
  if (result.isErr()) {    switch (result.error.name) {      case "CancelError":        // The user cancelled the operation        return;
      case "SigningError":        console.error(          `Failed to sign the transaction: ${result.error.message}`        );        break;
      case "TimeoutError":        console.error(`Transaction timed out: ${result.error.message}`);        break;
      case "TransactionError":        console.error(`Transaction failed: ${result.error.message}`);        break;
      default:        console.error(result.error.message);        break;    }    return;  }
  console.log("Borrow successful with hash:", result.value);};

Advanced Usage

Network Fee

This experimental AaveKit React hook currently works only with Viem or Wagmi integrations. Support for additional wallet libraries may be added later.

Estimate the network cost of any action using the same PreviewAction you pass to the usePreview hook.

Let's consider the following example:

PreviewAction
import { type PreviewAction } from "@aave/react";
const action: PreviewAction = {  borrow: {    sender: evmAddress("0x789…"), // User's address    reserve: reserve.id,    amount: {      erc20: {        value: bigDecimal(1000), // 1000 USDC      },    },  },};

Use the useNetworkFee hook to estimate both the network fee for the provided action and its fiat equivalent.

Viem
import { type PreviewAction, Currency } from "@aave/react";import { useNetworkFee } from "@aave/react/viem";
function NetworkFee({ action }: { action: PreviewAction }) {  const {    data: fee,    loading,    error,  } = useNetworkFee({    query: { estimate: action },    currency: Currency.Eur,  });
  if (loading) return <p>Loading fee…</p>;  if (error) return <p>Error: {error.message}</p>;
  return (    <p>      Network Fee: {fee.amount.value.toDisplayString(2)} {fee.token.info.symbol}      <span>{fee.fiatAmount.symbol}        {fee.fiatAmount.value.toDisplayString(2)}      </span>    </p>  );}

Native Tokens

When the Reserve's underlying token is the wrapped version of the chain's native token (e.g., WETH on Ethereum), you can borrow the asset as the chain's native token using the Native Token Gateway.

Use the asset.underlying.isWrappedNativeToken flag to determine if the underlying token is a wrapped native token. The Native Gateway address is available from the chain details.

WETH Reserve
const reserve: Reserve = {  id: "SGVsbG8h",  onChainId: "42",  borrowCap: "1000000000.000000", // 1B WETH  supplyCap: "2000000000.000000", // 2B WETH  canBorrow: true,  canSupply: true,  canUseAsCollateral: true,  asset: {    underlying: {      address: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",      info: {        name: "Wrapped Ether",        symbol: "WETH",        decimals: 18,        // …      },      isWrappedNativeToken: true,      // …    },    // …  },  spoke: {    address: "0x123…",    // …  },  chain: {    chainId: 1,    name: "Ethereum",    nativeGateway: "0xabc…",  },  // …};

Specify the amount in the amount field as a native value.

Borrow Native
const execute = async () => {  const result = await borrow({    sender: evmAddress(wallet.account.address), // User's address    reserve: reserve.id,    amount: {      native: bigDecimal(1), // 1 ETH    },  });
  // …};