Withdraw Assets
Learn how to withdraw assets from your Aave v4 supply positions.
Withdraw supplied assets from your Aave v4 positions to access your funds and any earned interest.
Withdrawing assets while having an open borrow position may reduce the collateralization ratio and lower the position's health factor. In some cases, this may put the position at risk of being liquidated.
Withdrawing
Withdrawing can be broken down into the following steps:
Identify the supply position to withdraw from
Preview the impact of the withdraw operation
Withdraw the assets
Identify the Supply Position
Given a list of user's supply positions, identify the supply position matching the token you want to withdraw and with a withdrawable amount that covers your needs.
The supplied position reserve should not be paused in order to withdraw from it.
For example, let’s say you have identified the following UserSupplyItem object.
Example UserSupplyItem
const supplyPosition: UserSupplyItem = { reserve: { id: "SGVsbG8h", onChainId: "42", chain: { chainId: 1, name: "Ethereum", }, spoke: { address: "0x123…", // … }, asset: { underlying: { address: "0xa0b86a33e6e2ad05ad6c9ac3b6e5e5f6e7b6c1b2", // USDC }, // … }, status: { paused: false, }, // … other reserve properties }, isCollateral: true, withdrawable: { amount: { value: "1000.000000", // 1,000 USDC supplied // … }, // … }, // …};Keep in mind that if the asset is used as collateral (isCollateral: true), withdrawing may:
Reduce your borrowing capacity and lower the position’s health factor, increasing the risk of liquidation.
If the collateral has a reserve.settings.collateralRisk greater than 0, lower the borrow APY on any open borrow positions in the same Spoke, effectively making those positions cheaper to maintain.
Preview Withdraw
Preview the impact of a withdraw operation before committing to it.
- React
- TypeScript
- GraphQL
- Solidity
Use the usePreview hook (or the imperative usePreviewAction variant) to preview the impact of the withdraw operation on the user's position.
Where the WithdrawRequest can be as follows:
You can also specify a different currency to return fiat amounts in.
The PreviewUserPosition shows the impact of the withdraw operation by comparing current and after states, with the table below outlining key fields and how to interpret them.
| Current → After | Impact | |
|---|---|---|
| healthFactor?.current → healthFactor?.after: BigDecimal | Higher is better | |
| riskPremium.current → riskPremium.after: PercentNumber | Lower is better | |
| netApy.current → netApy.after: PercentNumber | Higher is better | |
| netCollateral.current → netCollateral.after: FiatAmount | Higher is better | |
| netBalance.current → netBalance.after: FiatAmount | Updated balance |
Step-by-Step
- React
- TypeScript
- GraphQL
- Solidity
To withdraw assets from an Aave supply position with AaveKit React, follow these steps.
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);Finally, handle the result.
Example
const execute = async () => { const result = await withdraw(/* … */);
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(`Invalid withdrawal amount: ${result.error.message}`); break;
case "UnexpectedError": console.error(result.error.message); break; } return; }
console.log("Withdraw 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 = { withdraw: { sender: evmAddress("0x123…"), // User's address reserve: supplyPosition.reserve.id, amount: { erc20: { value: { exact: bigDecimal(42), // 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 withdraw the asset as the chain's native token using the Native Token Gateway.
Use the reserve.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 Supply Position
const supplyPosition: UserSupplyItem = { reserve: { id: "SGVsbG8h", onChainId: "42", 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.
- React
- TypeScript
- GraphQL
- Solidity