# Borrow Assets on Aave V3

Borrow assets from Aave V3 markets against your collateral, or delegate your borrowing power.

## Borrow Assets

Users can borrow assets from Aave markets at the reserve’s borrow APY using supply positions as collateral.

When borrowing assets from an Aave market, you can use the following methods:

| Method                | Description                                                 | Typical Scenario                                                                          |
| --------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
| **Direct Borrow**     | Borrow assets from a reserve using supplied collateral      | User borrows from a reserve against their own supplied collateral.                        |
| **Credit Delegation** | Borrow assets from a reserve using delegated borrow credits | User borrows from a reserve using credits from collateral supplied by a credit delegator. |

To borrow assets from an Aave market, follow these steps.

### 1. Identify the Borrow Reserve

First, determine which reserve you want to borrow assets from.

Given this `Reserve` object for WETH on an Ethereum market:

```ts title="Reserve"
const reserve: Reserve = {
  __typename: "Reserve",
  market: {
    __typename: "MarketInfo",
    address: "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2",
    chain: { chainId: 1 },
    // …
  },
  underlyingToken: {
    __typename: "Currency",
    symbol: "WETH",
    name: "Wrapped Ether",
    address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    // …
  },
  acceptsNative: {
    __typename: "NativeCurrency",
    symbol: "ETH",
    name: "Ethereum",
    // …
  },
  isFrozen: false,
  isPaused: false,
  userState: {
    __typename: "ReserveUserState",
    borrowable: {
      __typename: "TokenAmount",
      amount: {
        __typename: "DecimalValue",
        value: "15.75",
        raw: "15750000000000000000",
        decimals: 18,
        // …
      },
      // …
    },
  },
  // …
};
```

To borrow from the reserve, you need to verify these conditions:

- `Reserve.isFrozen` is `false` - the reserve is not frozen
- `Reserve.isPaused` is `false` - the reserve is not paused
- `Reserve.userState.borrowable.amount.value` is **greater than 0** - the amount the user can borrow from the reserve given their unique circumstances

> [!NOTE]
> Include a user address when fetching market and reserve data, or
> `Reserve.userState` will be empty.

Additionally, if `Reserve.acceptsNative` is not `null`, users can choose to receive any borrowed assets as the chain’s native token and it will be automatically unwrapped before being sent to the user’s wallet. This is typical for reserves of the wrapped version of the chain’s native token (e.g., WETH on Ethereum).

### 2. Prepare the Borrow Execution Plan

Next, if all of these conditions are met, we can proceed with creating the execution plan for the borrow operation.

Use the `useBorrow` hook in React, the `borrow` action in TypeScript, or the `borrow` query in GraphQL to create the execution plan for a direct borrow operation.

<tabgroup>
<tab label="React">

```tsx title="Direct ERC-20 Borrow"
import { useWalletClient } from "wagmi";
import { useBorrow, bigDecimal, evmAddress } from "@aave/react";

// …

const { data: walletClient } = useWalletClient();

const [borrow, borrowing] = useBorrow();

const execute = async () => {
  const result = await borrow({
    market: reserve.market.address,
    amount: {
      erc20: {
        currency: reserve.underlyingToken.address,
        value: bigDecimal(2), // 2 WETH
      },
    },
    sender: evmAddress(walletClient!.account.address),
    chainId: reserve.market.chain.chainId,
  });

  // …
};
```

```tsx title="Direct Native Borrow"
import { useWalletClient } from "wagmi";
import { useBorrow, bigDecimal, evmAddress } from "@aave/react";

// …

const { data: walletClient } = useWalletClient();

const [borrow, borrowing] = useBorrow();

const execute = async () => {
  const result = await borrow({
    market: reserve.market.address,
    amount: {
      native: bigDecimal(2), // 2 ETH
    },
    sender: evmAddress(walletClient!.account.address),
    chainId: reserve.market.chain.chainId,
  });

  // …
};
```

</tab>
<tab label="TypeScript">

```ts title="Direct ERC-20 Borrow"
import { borrow } from "@aave/client/actions";
import { bigDecimal, evmAddress } from "@aave/client";

import { client } from "./client";
import { wallet } from "./wallet";

const result = await borrow(client, {
  market: reserve.market.address,
  amount: {
    erc20: {
      currency: reserve.underlyingToken.address,
      value: bigDecimal(2), // 2 WETH
    },
  },
  sender: evmAddress(wallet.account.address),
  chainId: reserve.market.chain.chainId,
});

// …
```

```ts title="Direct Native Borrow"
import { borrow } from "@aave/client/actions";
import { bigDecimal, evmAddress } from "@aave/client";

import { client } from "./client";
import { wallet } from "./wallet";

const result = await borrow(client, {
  market: reserve.market.address,
  amount: {
    native: bigDecimal(2), // 2 ETH
  },
  sender: evmAddress(wallet.account.address),
  chainId: reserve.market.chain.chainId,
});

// …
```

```ts title="client.ts"
import { AaveClient } from "@aave/client";

export const client = AaveClient.create();
```

```ts title="wallet.ts"
import { createWalletClient, http, type Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";

export const wallet = createWalletClient({
  account: privateKeyToAccount(process.env.PRIVATE_KEY as Hex),
  chain: mainnet,
  transport: http(),
});
```

</tab>
<tab label="GraphQL">

```graphql title="Direct Borrow"
query {
  borrow(
    request: {
      market: "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2"
      amount: {
        erc20: {
          currency: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
          value: "2"
        }
        # OR
        # native: "2" # if the reserve accepts native currency
      }
      sender: "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"
      chainId: 1
    }
  ) {
    __typename
    ... on TransactionRequest {
      to
      from
      data
      value
      chainId
      operation
    }
    ... on ApprovalRequired {
      reason
      requiredAmount {
        value
        decimals
      }
      currentAllowance {
        value
        decimals
      }
      approval {
        to
        from
        data
        value
        chainId
        operation
      }
      originalTransaction {
        to
        from
        data
        value
        chainId
        operation
      }
    }
    ... on InsufficientBalanceError {
      required {
        value
        decimals
      }
      available {
        value
        decimals
      }
    }
  }
}
```

</tab>
</tabgroup>
If you intend to leverage credit delegation, you can first check the credit delegation allowance.

<tabgroup>
<tab label="React">

```tsx title="Check Credit Delegation Allowance"
import { useCreditDelegateeAllowance, evmAddress } from "@aave/react";

// …

const { data: allowance, loading } = useCreditDelegateeAllowance({
  market: reserve.market.address,
  underlyingToken: reserve.underlyingToken.address,
  user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"), // Delegator
  delegatee: evmAddress(walletClient!.account.address), // Your address
  chainId: reserve.market.chain.chainId,
});

if (allowance && BigInt(allowance.amount.raw) > 0n) {
  console.log("Available delegation allowance:", allowance.amount.value);
} else {
  console.log("No credit delegation allowance available");
}
```

</tab>
<tab label="TypeScript">

```ts title="Check Credit Delegation Allowance"
import { creditDelegateeAllowance } from "@aave/client/actions";
import { evmAddress } from "@aave/client";

import { client } from "./client";
import { wallet } from "./wallet";

const allowanceResult = await creditDelegateeAllowance(client, {
  market: reserve.market.address,
  underlyingToken: reserve.underlyingToken.address,
  user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"), // Delegator
  delegatee: evmAddress(wallet.account.address), // Your address
  chainId: reserve.market.chain.chainId,
});

if (allowanceResult.isOk() && BigInt(allowanceResult.value.amount.raw) > 0n) {
  console.log(
    "Available delegation allowance:",
    allowanceResult.value.amount.value
  );
} else {
  console.log("No credit delegation allowance available");
}
```

</tab>
<tab label="GraphQL">

```graphql title="Check Credit Delegation Allowance Query"
query {
  creditDelegateeAllowance(
    request: {
      market: "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2"
      underlyingToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
      user: "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234" # Delegator
      delegatee: "0x8ba1f109551bd432803012645ac136ddd64dba72" # Your address
      chainId: 1
    }
  ) {
    usdPerToken
    amount {
      value
      raw
      decimals
    }
    usd
  }
}
```

</tab>
</tabgroup>
And then, you can proceed with preparing the execution plan for the borrow operation.

<tabgroup>
<tab label="React">

```tsx title="Borrow with Credit Delegation"
import { useWalletClient } from "wagmi";
import { useBorrow, bigDecimal, evmAddress } from "@aave/react";

// …

const { data: walletClient } = useWalletClient();

const [borrow, borrowing] = useBorrow();

const execute = async () => {
  const result = await borrow({
    market: reserve.market.address,
    amount: {
      erc20: {
        currency: reserve.underlyingToken.address,
        value: bigDecimal(2), // 2 WETH
      },
    },
    sender: evmAddress(walletClient!.account.address),
    chainId: reserve.market.chain.chainId,
    onBehalfOf: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"), // Delegator
  });

  // …
};
```

</tab>
<tab label="TypeScript">

```ts title="Borrow with Credit Delegation"
import { borrow } from "@aave/client/actions";
import { bigDecimal, evmAddress } from "@aave/client";

import { client } from "./client";
import { wallet } from "./wallet";

const result = await borrow(client, {
  market: reserve.market.address,
  amount: {
    erc20: {
      currency: reserve.underlyingToken.address,
      value: bigDecimal(2), // 2 WETH
    },
  },
  sender: evmAddress(wallet.account.address),
  chainId: reserve.market.chain.chainId,
  onBehalfOf: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"), // Delegator
});

// …
```

</tab>
<tab label="GraphQL">

```graphql title="Borrow with Credit Delegation"
query {
  borrow(
    request: {
      market: "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2"
      amount: {
        erc20: {
          currency: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
          value: "2"
        }
        # OR
        # native: "2" # if the reserve accepts native currency
      }
      sender: "0x8ba1f109551bd432803012645ac136ddd64dba72" # Delegatee
      chainId: 1
      onBehalfOf: "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234" # Delegator
    }
  ) {
    # …
  }
}
```

</tab>
</tabgroup>
### 3. Process the Borrow Execution Plan

Finally, handle the execution plan.

- **React**: Use the `useSendTransaction` hook for the [wallet library of your choice](../getting-started/react#send-aave-transactions) to send the transactions in the execution plan.
- **TypeScript**: Use `sendWith` for your [chosen wallet library](../getting-started/typescript#send-aave-transactions) to send the transactions in the execution plan, and await indexing with `client.waitForTransaction`.
- **GraphQL**: If the response is a `TransactionRequest`, you can send it directly using the wallet associated with the from address.

<tabgroup>
<tab label="React">

```tsx title="Viem"
import { useWalletClient } from "wagmi";
import { errAsync, useBorrow } from "@aave/react";
import { useSendTransaction } from "@aave/react/viem";

// …

const { data: walletClient } = useWalletClient();

const [borrow, borrowing] = useBorrow();
const [sendTransaction, sending] = useSendTransaction(walletClient);

// …

// Optional: combine loading states
const loading = borrowing.loading || sending.loading;
const error = borrowing.error || sending.error;

// …

const execute = async () => {
  const result = await borrow({
    // …
  }).andThen((plan) => {
    switch (plan.__typename) {
      case "TransactionRequest":
        // Single transaction execution
        return sendTransaction(plan);

      case "ApprovalRequired":
        // Approval + transaction sequence
        return sendTransaction(plan.approval).andThen(() =>
          sendTransaction(plan.originalTransaction)
        );

      case "InsufficientBalanceError":
        return errAsync(
          new Error(`Insufficient balance: ${plan.required.value} required.`)
        );
    }
  });

  if (result.isErr()) {
    console.error("Borrow failed:", result.error);
  } else {
    console.log("Borrow successful with hash:", result.value);
  }
};
```

</tab>
<tab label="TypeScript">

```ts title="Viem"
import { borrow } from "@aave/client/actions";
import { sendWith } from "@aave/client/viem";

import { client } from "./client";
import { wallet } from "./wallet";

const result = await borrow(client, {
  // …
})
  .andThen(sendWith(wallet))
  .andThen(client.waitForTransaction);

if (result.isErr()) {
  console.error("Borrow failed:", result.error);
} else {
  console.log("Borrow successful:", result.value);
}
```

</tab>
<tab label="GraphQL">

```json title="TransactionRequest"
{
  "data": {
    "borrow": {
      "__typename": "TransactionRequest",
      "to": "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2",
      "from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
      "data": "0xa415bcad000000000000000000000000a0b…",
      "value": "0",
      "chainId": 1,
      "operation": "BORROW"
    }
  }
}
```

</tab>
</tabgroup>
In GraphQL, if the response is an `ApprovalRequired`, you must first send the `approval` transaction. Once it succeeds, you can then send the `originalTransaction`. This happens only for native borrows, which need credit delegation to the WrappedTokenGateway.

```json title="ApprovalRequired"
{
  "data": {
    "borrow": {
      "__typename": "ApprovalRequired",
      "reason": "Insufficient credit delegation to the WrappedTokenGateway",
      "requiredAmount": {
        "value": "2.0",
        "decimals": 18
      },
      "currentAllowance": {
        "value": "0.0",
        "decimals": 18
      },
      "approval": {
        "to": "0xeA51d7853EEFb32b6ee06b1C12E6dcCA88Be0fFE",
        "from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
        "data": "0xc04a8a10000000000000000000000000d01…",
        "value": "0",
        "chainId": 1,
        "operation": null
      },
      "originalTransaction": {
        "to": "0xd01607c3C5eCABa394D8be377a08590149325722",
        "from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
        "data": "0xe74f7b85000000000000000000000000878…",
        "value": "0",
        "chainId": 1,
        "operation": "BORROW"
      }
    }
  }
}
```

In GraphQL, if the response is an `InsufficientBalanceError`, inform the user that they don’t have enough balance to borrow the requested amount.

```json title="InsufficientBalanceError"
{
  "data": {
    "borrow": {
      "__typename": "InsufficientBalanceError",
      "required": {
        "value": "2.0",
        "decimals": 18
      },
      "available": {
        "value": "1.0",
        "decimals": 18
      }
    }
  }
}
```

## Credit Delegation

Credit delegation allows a user to approve another user (delegatee) to borrow assets against their own supply position. The supply position must be enabled as collateral.

To delegate credit to another address, follow these steps.

### 1. Identify the Delegated Position

First, choose the asset the delegatee may borrow and make sure your collateral is enabled.

Given this `MarketUserReserveSupplyPosition` object:

```ts title="MarketUserReserveSupplyPosition"
const position: MarketUserReserveSupplyPosition = {
  __typename: "MarketUserReserveSupplyPosition",
  market: {
    __typename: "MarketInfo",
    address: "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2",
    chain: { chainId: 1 },
    // …
  },
  currency: {
    __typename: "Currency",
    symbol: "WETH",
    name: "Wrapped Ether",
    address: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
    // …
  },
  balance: {
    __typename: "TokenAmount",
    amount: {
      __typename: "DecimalValue",
      value: "5.0",
      raw: "5000000000000000000",
      decimals: 18,
      // …
    },
    // …
  },
  isCollateral: true,
  canBeCollateral: true,
  // …
};
```

Ensure `MarketUserReserveSupplyPosition.isCollateral` is `true`, if not [enable it as collateral](./supply#collateral-management) first.

### 2. Prepare the Delegation Transaction Request

Next, we can proceed with creating the transaction request for the credit delegation operation.

Use the `useApproveBorrowCreditDelegation` hook in React, the `approveBorrowCreditDelegation` action in TypeScript, or the `approveBorrowCreditDelegation` query in GraphQL to create the transaction request for approving credit delegation. `underlyingToken` is the asset the delegatee will borrow; the example uses WETH.

<tabgroup>
<tab label="React">

```tsx title="Approve Credit Delegation"
import { useWalletClient } from "wagmi";
import {
  useApproveBorrowCreditDelegation,
  evmAddress,
  bigDecimal,
} from "@aave/react";

// …

const { data: walletClient } = useWalletClient();

const [approveDelegation, approving] = useApproveBorrowCreditDelegation();

const execute = async () => {
  const result = await approveDelegation({
    market: position.market.address,
    underlyingToken: position.currency.address,
    amount: bigDecimal(1000),
    user: evmAddress(walletClient!.account.address),
    delegatee: evmAddress("0x8ba1f109551bd432803012645ac136ddd64dba72"),
    chainId: position.market.chain.chainId,
  });

  // …
};
```

</tab>
<tab label="TypeScript">

```ts title="Approve Credit Delegation"
import { approveBorrowCreditDelegation } from "@aave/client/actions";
import { evmAddress, bigDecimal } from "@aave/client";

import { client } from "./client";
import { wallet } from "./wallet";

const result = await approveBorrowCreditDelegation(client, {
  market: position.market.address,
  underlyingToken: position.currency.address,
  amount: bigDecimal(1000),
  user: evmAddress(wallet.account.address),
  delegatee: evmAddress("0x8ba1f109551bd432803012645ac136ddd64dba72"),
  chainId: position.market.chain.chainId,
});

// …
```

```ts title="client.ts"
import { AaveClient } from "@aave/client";

export const client = AaveClient.create();
```

```ts title="wallet.ts"
import { createWalletClient, http, type Hex } from "viem";
import { privateKeyToAccount } from "viem/accounts";
import { mainnet } from "viem/chains";

export const wallet = createWalletClient({
  account: privateKeyToAccount(process.env.PRIVATE_KEY as Hex),
  chain: mainnet,
  transport: http(),
});
```

</tab>
<tab label="GraphQL">

```graphql title="Query"
query {
  approveBorrowCreditDelegation(
    request: {
      market: "0x87870bca3f3fd6335c3f4ce8392d69350b4fa4e2"
      underlyingToken: "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
      amount: "1000"
      user: "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"
      delegatee: "0x8ba1f109551bd432803012645ac136ddd64dba72"
      chainId: 1
    }
  ) {
    to
    from
    data
    value
    chainId
  }
}
```

</tab>
</tabgroup>
### 3. Send the Delegation Transaction

Finally, send the transaction.

- **React**: Use the `useSendTransaction` hook for the [wallet library of your choice](../getting-started/react#send-aave-transactions) to send the transaction.
- **TypeScript**: Use `sendWith` for your [chosen wallet library](../getting-started/typescript#send-aave-transactions) to initiate the transaction, and await indexing with `client.waitForTransaction`.
- **GraphQL**: The response is a `TransactionRequest` that can be sent directly using the wallet associated with the `from` address.

<tabgroup>
<tab label="React">

```tsx title="Viem"
import { useWalletClient } from "wagmi";
import { useApproveBorrowCreditDelegation } from "@aave/react";
import { useSendTransaction } from "@aave/react/viem";

// …

const { data: walletClient } = useWalletClient();

const [approveDelegation, approving] = useApproveBorrowCreditDelegation();
const [sendTransaction, sending] = useSendTransaction(walletClient);

// …

// Optional: combine loading states
const loading = approving.loading || sending.loading;
const error = approving.error || sending.error;

// …

const execute = async () => {
  const result = await approveDelegation({
    // …
  }).andThen(sendTransaction);

  if (result.isErr()) {
    console.error("Credit delegation failed:", result.error);
  } else {
    console.log("Credit delegation successful with hash:", result.value);
  }
};
```

</tab>
<tab label="TypeScript">

```ts title="Viem"
import { approveBorrowCreditDelegation } from "@aave/client/actions";
import { sendWith } from "@aave/client/viem";

import { client } from "./client";
import { wallet } from "./wallet";

const result = await approveBorrowCreditDelegation(client, {
  // …
})
  .andThen(sendWith(wallet))
  .andThen(client.waitForTransaction);

if (result.isErr()) {
  console.error("Credit delegation failed:", result.error);
} else {
  console.log("Credit delegation successful:", result.value);
}
```

</tab>
<tab label="GraphQL">

```json title="TransactionRequest"
{
  "data": {
    "approveBorrowCreditDelegation": {
      "__typename": "TransactionRequest",
      "to": "0xeA51d7853EEFb32b6ee06b1C12E6dcCA88Be0fFE",
      "from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
      "data": "0xc04a8a10…",
      "value": "0",
      "chainId": 1,
      "operation": null
    }
  }
}
```

</tab>
</tabgroup>
The delegatee can now borrow against the user’s supply position.
