# Borrow Assets on Aave V4

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

> [!WARNING]
> Borrowing lowers your health factor. Keep enough collateral and watch the
> health factor, especially in volatile markets, to avoid liquidation.

## Borrow Assets

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`.

```tsx title="Reserves List"
const reserves: Reserve[] = [
  {
    id: "SGVsbG8h",
    onChainId: "42",
    canBorrow: true,
    settings: {
      borrowCap: {
        amount: { value: BigDecimal(1000000000.0) }, // 1B USDC
        // …
      },
      // …
    },
    status: {
      frozen: false,
      paused: false,
    },
    spoke: {
      address: "0x123…",
      // …
    },
    // …
  },
  {
    id: "V29ybGQh",
    onChainId: "43",
    canBorrow: false, // cannot borrow from this reserve
    settings: {
      borrowCap: {
        amount: { value: BigDecimal(500000000.0) }, // 500M DAI
        // …
      },
      // …
    },
    status: {
      frozen: true, // reserve is frozen
      paused: false,
    },
    spoke: {
      address: "0x123…",
      // …
    },
    // …
  },
  // …
];
```

> [!NOTE]
> `canBorrow` means the reserve is active: not frozen, not paused, and below its
> borrow cap.

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](../positions#user-risk-premium) tied to the position’s collateral

```tsx title="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: BigDecimal(3.73), // 3.73% APY
      // …
    },
    borrowable: {
      amount: {
        value: BigDecimal(10000.0), // 10,000 USDC
      },
      // …
    },
    // …
  },
};
```

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

### Preview Borrow with AaveKit

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

Use the `usePreview` hook (or the imperative `usePreviewAction` variant) in React, the `preview` action in TypeScript, or the `preview` query in GraphQL to preview the impact of the borrow operation on the user’s position.

<tabgroup>
<tab label="React">

```tsx title="Loading State"
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>
      From: {data.healthFactor.current?.toFixed(2) ?? "N/A"}
      To: {data.healthFactor.after?.toFixed(2) ?? "N/A"}

      <h3>User Risk Premium:</h3>
      From: {data.riskPremium.current.normalized.toFixed(2)}%
      To: {data.riskPremium.after.normalized.toFixed(2)}%

      <h3>Net APY:</h3>
      From: {data.netApy.current.normalized.toFixed(2)}%
      To: {data.netApy.after.normalized.toFixed(2)}%

      <h3>Net Collateral:</h3>
      From: {data.netCollateral.current.value.toDisplayString(2)}
      To: {data.netCollateral.after.value.toDisplayString(2)}
    </div>
  );
}
```

```tsx title="React Suspense"
import { type BorrowRequest, usePreview } from "@aave/react";

function BorrowPreview({ request }: { request: BorrowRequest }) {
  const { data, error, loading } = usePreview({
    action: {
      borrow: request,
    },
    suspense: true,
  });

  // data: PreviewUserPosition
  return (
    <div>
      <h3>Health Factor:</h3>
      From: {data.healthFactor.current?.toFixed(2) ?? "N/A"}
      To: {data.healthFactor.after?.toFixed(2) ?? "N/A"}

      <h3>User Risk Premium:</h3>
      From: {data.riskPremium.current.normalized.toFixed(2)}%
      To: {data.riskPremium.after.normalized.toFixed(2)}%

      <h3>Net APY:</h3>
      From: {data.netApy.current.normalized.toFixed(2)}%
      To: {data.netApy.after.normalized.toFixed(2)}%

      <h3>Net Collateral:</h3>
      From: {data.netCollateral.current.value.toDisplayString(2)}
      To: {data.netCollateral.after.value.toDisplayString(2)}
    </div>
  );
}
```

```tsx title="Imperative Read"
import { type BorrowRequest, usePreviewAction } from "@aave/react";

const [preview, { called, data, error, loading }] = usePreviewAction();

const handler = async (request: BorrowRequest) => {
  const result = await preview({
    action: {
      borrow: request,
    },
  });

  if (result.isOk()) {
    console.log(result.value); // PreviewUserPosition
  } else {
    console.error(result.error);
  }
};
```

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

```ts title="Preview"
import { preview } from "@aave/client/actions";
import { bigDecimal, evmAddress } from "@aave/client";

const result = await preview(client, {
  action: {
    borrow: {
      sender: evmAddress("0x789…"), // User's address
      reserve: reserve.id,
      amount: {
        erc20: {
          value: bigDecimal(1000), // 1000 USDC
        },
      },
    },
  },
});

if (result.isOk()) {
  console.log(result.value); // PreviewUserPosition
} else {
  console.error(result.error);
}
```

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

```graphql title="Query"
query ($request: PreviewRequest!, $currency: Currency = USD) {
  preview(request: $request) {
    __typename
    id
    healthFactor {
      ...HealthFactorResult
    }
    netApy {
      ...PercentNumberVariation
    }
    riskPremium {
      ...PercentNumberVariation
    }
    netCollateral(currency: $currency) {
      ...ExchangeAmountVariation
    }
    netBalance(currency: $currency) {
      ...ExchangeAmountVariation
    }
    projectedEarnings {
      ...ExchangeAmountVariation
    }
    maxBorrowingPower {
      ...ExchangeAmountVariation
    }
    remainingBorrowingPower {
      ...ExchangeAmountVariation
    }
    reserveRates {
      supplyApy {
        ...PercentNumberVariation
      }
      borrowApy {
        ...PercentNumberVariation
      }
    }
    otherConditions {
      ...UserPositionConditionVariation
    }
  }
}
```

```graphql title="HealthFactorResult"
fragment HealthFactorResult on HealthFactorResult {
  __typename
  ... on HealthFactorVariation {
    ...HealthFactorVariation
  }
  ... on HealthFactorError {
    ...HealthFactorError
  }
}

fragment HealthFactorVariation on HealthFactorVariation {
  __typename
  current
  after
}

fragment HealthFactorError on HealthFactorError {
  __typename
  reason
  current
  after
}
```

```graphql title="UserPositionConditionVariation"
fragment UserPositionConditionVariation on UserPositionConditionVariation {
  __typename
  ... on CollateralFactorVariation {
    reserveId
    token {
      ...Erc20Token
    }
    current {
      ...PercentNumber
    }
    after {
      ...PercentNumber
    }
  }
  ... on LiquidationFeeVariation {
    reserveId
    token {
      ...Erc20Token
    }
    current {
      ...PercentNumber
    }
    after {
      ...PercentNumber
    }
  }
  ... on MaxLiquidationBonusVariation {
    reserveId
    token {
      ...Erc20Token
    }
    current {
      ...PercentNumber
    }
    after {
      ...PercentNumber
    }
  }
}
```

```graphql title="Others"
fragment PercentNumberVariation on PercentNumberVariation {
  __typename
  current {
    ...PercentNumber
  }
  after {
    ...PercentNumber
  }
}

fragment ExchangeAmountVariation on ExchangeAmountVariation {
  __typename
  current {
    ...ExchangeAmount
  }
  after {
    ...ExchangeAmount
  }
}
```

</tab>
</tabgroup>
- **React**: The `BorrowRequest` can be as follows.
- **GraphQL**: The `PreviewRequest` can be as follows.

<tabgroup>
<tab label="React">

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

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

```json title="Borrow ERC-20"
{
  "request": {
    "action": {
      "borrow": {
        "sender": "0x789…",
        "reserve": "SGVsbG8h",
        "amount": {
          "erc20": {
            "value": "1000"
          }
        }
      }
    }
  }
}
```

</tab>
</tabgroup>
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.

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

<tabgroup>
<tab label="React">

```ts title="usePreview"
import { Currency } from "@aave/react";

const { data, error, loading } = usePreview({
  action: {
    borrow: request,
  },
  currency: Currency.Eur,
});
```

```ts title="usePreviewAction"
import { Currency } from "@aave/react";

const [preview, { called, data, error, loading }] = usePreviewAction({
  currency: Currency.Eur,
});
```

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

```ts title="Custom Currency"
import { Currency } from "@aave/client";

const result = await preview(
  client,
  {
    action: {
      borrow: ,
    },
  },
  {
    currency: Currency.Eur,
  },
);
```

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

```jsonc title="Custom Currency"
{
  "request": {
    "action": {
      "borrow": {
        // …
      }
    }
  },
  "currency": "EUR"
}
```

</tab>
</tabgroup>
### Preview Borrow with Solidity

Start with the spoke address and on-chain reserve ID identified:

<tabgroup>
<tab label="Solidity">

```solidity title="Target Reserve"
address spokeAddress = 0x123…;
uint256 reserveId = 42;
```

</tab>
</tabgroup>
And an amount to borrow:

<tabgroup>
<tab label="Solidity">

```solidity title="Amount to Borrow"
uint256 amountToBorrow = 42e6; // 42 USDC
```

</tab>
</tabgroup>
Follow the steps below to preview the impact of a borrow operation on the user’s position.

#### 1. Get Current Account Data

First, retrieve the user’s current account data from the Spoke contract.

<tabgroup>
<tab label="Solidity">

```solidity title="Get Account Data"
import { ISpoke } from "aave-v4/src/spoke/interfaces/ISpoke.sol";

ISpoke spoke = ISpoke(spokeAddress);
ISpoke.UserAccountData memory currentData = spoke.getUserAccountData(user);
```

</tab>
</tabgroup>
#### 2. Calculate New Debt Value

Then, retrieve the reserve data and asset price from the oracle to calculate the USD value of the new borrow, and add it to the current total debt.

<tabgroup>
<tab label="Solidity">

```solidity title="New Debt Value"
address oracleAddress = spoke.ORACLE();
ISpoke.Reserve memory reserve = spoke.getReserve(reserveId);
uint256 assetPrice = IAaveOracle(oracleAddress).getReservePrice(reserveId);
uint256 borrowValue = amountToBorrow * assetPrice * 10 ** (18 - reserve.decimals);
uint256 newTotalDebtValue = currentData.totalDebtValueRay / 1e27 + borrowValue;
```

</tab>
</tabgroup>
#### 3. Compute New Health Factor

Finally, calculate the new health factor by incorporating the new debt value.

<tabgroup>
<tab label="Solidity">

```solidity title="Compute New Health Factor"
uint256 newHealthFactor = (currentData.totalCollateralValue * currentData.avgCollateralFactor) / newTotalDebtValue; // WAD, 1e18 = 1.00
```

</tab>
</tabgroup>
#### Complete Preview Example

Here’s a complete Solidity example that calculates the health factor before a borrow operation:

<tabgroup>
<tab label="Solidity">

```solidity title="Complete Health Factor Preview"
import { ISpoke } from "aave-v4/src/spoke/interfaces/ISpoke.sol";
import { IAaveOracle } from "aave-v4/src/spoke/interfaces/IAaveOracle.sol";

function previewBorrowHealthFactor(
  address spokeAddress,
  uint256 reserveId,
  uint256 amountToBorrow,
  address user
) external view returns (uint256) {
  ISpoke spoke = ISpoke(spokeAddress);
  IAaveOracle oracle = IAaveOracle(spoke.ORACLE());

  // Step 1: Get Current Account Data
  ISpoke.UserAccountData memory currentData = spoke.getUserAccountData(user);

  // Step 2: Calculate New Debt Value
  ISpoke.Reserve memory reserve = spoke.getReserve(reserveId);
  uint256 assetPrice = oracle.getReservePrice(reserveId);
  uint256 borrowValue = amountToBorrow * assetPrice * 10 ** (18 - reserve.decimals);
  uint256 newTotalDebtValue = currentData.totalDebtValueRay / 1e27 + borrowValue;

  // Step 3: Compute New Health Factor
  return (currentData.totalCollateralValue * currentData.avgCollateralFactor) / newTotalDebtValue; // WAD, 1e18 = 1.00
}
```

</tab>
</tabgroup>
### Step-by-Step with AaveKit

Borrow assets from the selected reserve.

> [!WARNING]
> Borrowing increases risk and updates the Dynamic Config, which updates the
> position’s User Risk Premium. See [User Position Conditions](./conditions).

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

#### 1. Configure Wallet Integration

In React, first instantiate the `useSendTransaction` hook for the [wallet library of your choice](../getting-started/react#integrations).

<tabgroup>
<tab label="React">

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

// …

const { data: wallet } = useWalletClient();
const [sendTransaction] = useSendTransaction(wallet);
```

</tab>
</tabgroup>
#### 2. Define the Borrow Flow

Then, in React, use the `useBorrow` hook to prepare the borrow operation.

<tabgroup>
<tab label="React">

```tsx title="Basic Usage"
import { useBorrow } from "@aave/react";

const [borrow, { loading, error }] = useBorrow((plan) => {
  switch (plan.__typename) {
    case "TransactionRequest":
      return sendTransaction(plan);

    case "PreContractActionRequired":
      return sendTransaction(plan.transaction);
  }
});
```

```tsx title="Update Component State"
import { useBorrow } from "@aave/react";

const [status, setStatus] = useState("");

const [borrow, { loading, error }] = useBorrow((plan) => {
  switch (plan.__typename) {
    case "TransactionRequest":
      setStatus("Please sign the Borrow transaction in your wallet");
      return sendTransaction(plan).andTee(() => setStatus("Borrowing…"));

    case "PreContractActionRequired":
      setStatus("Please sign the Pre-Contract Action in your wallet");
      return sendTransaction(plan.transaction).andTee(() =>
        setStatus("Processing…"),
      );
  }
});
```

```tsx title="Cancel Flow"
import { useBorrow } from "@aave/react";

const [borrow, { loading, error }] = useBorrow((plan, { cancel }) => {
  if (window.confirm("Are you sure you want to continue?") === false) {
    return cancel("User cancelled the operation");
  }

  switch (plan.__typename) {
    case "TransactionRequest":
      return sendTransaction(plan);

    case "PreContractActionRequired":
      return sendTransaction(plan.transaction);
  }
});
```

</tab>
</tabgroup>
#### 3. Execute the Borrow Operation

Then, execute the desired borrow operation.

- **TypeScript**: Use the `borrow` action to prepare the borrow execution plan.
- **GraphQL**: Use the `borrow` query to prepare the borrow execution plan.

<tabgroup>
<tab label="React">

```tsx title="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
      },
    },
  });

  // …
};
```

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

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

import { client } from "./client";

const result = await borrow(client, {
  sender: evmAddress(wallet.account.address), // User's address
  reserve: reserve.id,
  amount: {
    erc20: {
      value: bigDecimal(100), // 100 USDC
    },
  },
});

// …
```

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

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

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

```graphql title="Query"
query ($request: BorrowRequest!) {
  borrow(request: $request) {
    __typename

    ... on TransactionRequest {
      ...TransactionRequest
    }

    ... on PreContractActionRequired {
      reason
      transaction {
        ...TransactionRequest
      }
      originalTransaction {
        ...TransactionRequest
      }
    }
  }
}
```

```graphql title="TransactionRequest"
fragment TransactionRequest on TransactionRequest {
  to
  from
  data
  value
  chainId
  operations
}
```

</tab>
</tabgroup>
In GraphQL, below is an example of a `BorrowRequest` object.

<tabgroup>
<tab label="GraphQL">

```json title="Variables"
{
  "request": {
    "sender": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
    "reserve": "SGVsbG8h",
    "amount": {
      "erc20": {
        "value": "100"
      }
    }
  }
}
```

</tab>
</tabgroup>
#### 4. Process the Execution Plan

In TypeScript, use `sendWith` for the [wallet library of your choice](../getting-started/typescript#integrations) to send the transactions in the execution plan, and await indexing with `client.waitForTransaction`.

<tabgroup>
<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);
```

```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>
</tabgroup>
In GraphQL, if the response is a `TransactionRequest`, you can send it directly using the wallet associated with the from address.

<tabgroup>
<tab label="GraphQL">

```json title="TransactionRequest"
{
  "data": {
    "borrow": {
      "__typename": "TransactionRequest",
      "to": "0x94e7a5dcbe816e498b89ab752661904e2f56c485",
      "from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
      "data": "0xd6bda0c0…",
      "value": "0",
      "chainId": 1,
      "operations": ["SPOKE_BORROW"]
    }
  }
}
```

</tab>
</tabgroup>
If the response is a `PreContractActionRequired`, you must first send the `transaction` request. Once it succeeds, you can then send the `originalTransaction`.

<tabgroup>
<tab label="GraphQL">

```json title="PreContractActionRequired"
{
  "data": {
    "borrow": {
      "__typename": "PreContractActionRequired",
      "reason": "Authorize the native wrapping gateway to operate on behalf of the user",
      "transaction": {
        "to": "0x94e7a5dcbe816e498b89ab752661904e2f56c485",
        "from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
        "data": "0x095ea7b3000000000000000000000000878…",
        "value": "0",
        "chainId": 1,
        "operations": null
      },
      "originalTransaction": {
        "to": "0x94e7a5dcbe816e498b89ab752661904e2f56c485",
        "from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
        "data": "0xd6bda0c0…",
        "value": "0",
        "chainId": 1,
        "operations": ["SPOKE_BORROW"]
      }
    }
  }
}
```

</tab>
</tabgroup>
#### 5. Handle the Result

Finally, in React and TypeScript, handle the result.

<tabgroup>
<tab label="React">

```tsx title="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;

      case "ValidationError":
        console.error(
          "Insufficient balance:",
          `required: ${result.error.cause.required.value.toDisplayString(2)}`,
          `available: ${result.error.cause.available.value.toDisplayString(2)}`,
        );
        break;

      case "UnexpectedError":
        console.error(result.error.message);
        break;
    }
    return;
  }

  console.log("Borrow successful with hash:", result.value.txHash);
};
```

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

```ts title="Example"
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;

    case "ValidationError":
      console.error(
        "Insufficient balance:",
        `required: ${result.error.cause.required.value.toDisplayString(2)}`,
        `available: ${result.error.cause.available.value.toDisplayString(2)}`,
      );
      break;

    case "UnexpectedError":
      console.error(result.error.message);
      break;
  }
  return;
}

console.log("Borrow successful with hash:", result.value.txHash);
```

</tab>
</tabgroup>
### Step-by-Step with Solidity

Use the same identifiers and amount to borrow used to preview the borrow operation:

<tabgroup>
<tab label="Solidity">

```solidity title="Target Reserve"
address spokeAddress = 0x123…;
uint256 reserveId = 42;

uint256 amountToBorrow = 42e6; // 42 USDC
```

</tab>
</tabgroup>
Complete the borrow process with the following steps:

#### 1. Import the Spoke Interface

First, create an instance of the `ISpoke` interface.

<tabgroup>
<tab label="Solidity">

```solidity title="Import the Spoke Interface"
import { ISpoke } from "aave-v4/src/spoke/interfaces/ISpoke.sol";

ISpoke spoke = ISpoke(spokeAddress);
```

</tab>
</tabgroup>
#### 2. Borrow Assets

Then, call the `borrow` function on the Spoke contract, specifying the reserve ID, amount to borrow, and the `onBehalfOf` address (the position owner). The borrowed tokens are sent to the caller (`msg.sender`).

<tabgroup>
<tab label="Solidity">

```solidity title="Borrow"
spoke.borrow(
  reserveId,
  amountToBorrow,
  msg.sender
);
```

</tab>
</tabgroup>
#### Complete Borrow Example

Here’s a complete Solidity example that executes the borrow operation:

<tabgroup>
<tab label="Solidity">

```solidity title="Complete Borrow Flow"
import { ISpoke } from "aave-v4/src/spoke/interfaces/ISpoke.sol";

function borrowFromReserve(
  address spokeAddress,
  uint256 reserveId,
  uint256 amountToBorrow,
  address onBehalfOf
) external {
  // Borrow assets from reserve
  ISpoke(spokeAddress).borrow(reserveId, amountToBorrow, onBehalfOf);
}
```

</tab>
</tabgroup>
---

## Advanced Usage

### Network Fee

> [!NOTE]
> This experimental React hook only works with Viem or Wagmi integrations.

<NetworkFee>

```tsx title="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
      },
    },
  },
};
```

</NetworkFee>

### Native Tokens with AaveKit

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 Token Gateway address is available from the chain details.

```ts title="WETH Reserve"
const reserve: Reserve = {
  id: "SGVsbG8h",
  onChainId: "42",
  canBorrow: true,
  canSupply: true,
  canUseAsCollateral: true,
  asset: {
    underlying: {
      address: "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
      info: {
        name: "Wrapped Ether",
        symbol: "WETH",
        decimals: 18,
        // …
      },
      isWrappedNativeToken: true,
      // …
    },
    // …
  },
  settings: {
    borrowCap: {
      amount: { value: BigDecimal(1000000000.0) }, // 1B WETH
      // …
    },
    supplyCap: {
      amount: { value: BigDecimal(2000000000.0) }, // 2B WETH
      // …
    },
    // …
  },
  spoke: {
    address: "0x123…",
    // …
  },
  chain: {
    chainId: 1,
    name: "Ethereum",
    nativeGateway: "0xabc…",
  },
  // …
};
```

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

<tabgroup>
<tab label="React">

```tsx title="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
    },
  });

  // …
};
```

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

```ts title="Borrow Native"
const result = await borrow(client, {
  sender: evmAddress(wallet.account.address), // User's address
  reserve: reserve.id,
  amount: {
    native: bigDecimal(1), // 1 ETH
  },
});

// …
```

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

```jsonc title="Borrow Native"
{
  "request": {
    "sender": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
    "reserve": "SGVsbG8h",
    "amount": {
      "native": "1" // 1 ETH
    }
  }
}
```

</tab>
</tabgroup>
### Native Tokens with Solidity

Start with the spoke address, reserve ID, and native gateway address identified:

<tabgroup>
<tab label="Solidity">

```solidity title="Native Token Gateway"
address spokeAddress = 0x123…;
uint256 reserveId = 42;
address nativeGateway = 0xabc…;
```

</tab>
</tabgroup>
Follow the steps below to borrow native tokens (e.g., ETH) from a wrapped native token reserve (e.g., WETH).

#### 1. Approve the Gateway

First, approve the Native Token Gateway as your position manager. This is a one-time setup step.

<tabgroup>
<tab label="Solidity">

```solidity title="Approve Gateway"
import { ISpoke } from "aave-v4/src/spoke/interfaces/ISpoke.sol";

ISpoke spoke = ISpoke(spokeAddress);
spoke.setUserPositionManager(nativeGateway, true);
```

</tab>
</tabgroup>
#### 2. Borrow Native Tokens

Then, call `borrowNative` on the gateway to borrow and unwrap the tokens.

<tabgroup>
<tab label="Solidity">

```solidity title="Borrow Native"
import { INativeTokenGateway } from "aave-v4/src/position-manager/interfaces/INativeTokenGateway.sol";

INativeTokenGateway gateway = INativeTokenGateway(nativeGateway);
gateway.borrowNative(spokeAddress, reserveId, amountToBorrow);
```

</tab>
</tabgroup>
The gateway calls `spoke.borrow` on your behalf, unwraps the token (WETH → ETH), and sends the native token to the caller (`msg.sender`).

#### Complete Native Token Example

Here’s a complete Solidity example for borrowing native tokens. This helper acts on the contract’s own position. The gateway sends the native tokens to the contract, so it needs a `receive()` function. To borrow for a user’s wallet, the user calls `setUserPositionManager` and the gateway directly.

<tabgroup>
<tab label="Solidity">

```solidity title="Complete Native Borrow Flow"
import { ISpoke } from "aave-v4/src/spoke/interfaces/ISpoke.sol";
import { INativeTokenGateway } from "aave-v4/src/position-manager/interfaces/INativeTokenGateway.sol";

function borrowNativeToken(
  address spokeAddress,
  address nativeGateway,
  uint256 reserveId,
  uint256 amountToBorrow
) external {
  ISpoke spoke = ISpoke(spokeAddress);

  // Step 1: Approve gateway as position manager (one-time setup)
  if (!spoke.isPositionManager(address(this), nativeGateway)) {
    spoke.setUserPositionManager(nativeGateway, true);
  }

  // Step 2: Borrow native tokens via gateway
  INativeTokenGateway(nativeGateway).borrowNative(spokeAddress, reserveId, amountToBorrow);
}

receive() external payable {}
```

</tab>
</tabgroup>
