WDK logoWDK documentation
AaveGuides

Lending Operations

Supply, withdraw, borrow, repay, quote fees, use ERC-4337, and read account data.

This guide walks through supply, withdraw, borrow, repay, quotes, ERC-4337 usage, and reading account data. It assumes an AaveProtocolEvm instance named aave and the USD₮ contract on Ethereum mainnet 0xdAC17F958D2ee523a2206206994597C13D831ec7.

Supply

Before supplying, confirm sufficient token allowance to the Aave Pool for your chain. Send any required approval through the wallet account and wait for confirmation. The lending module does not approve or reset allowances automatically.

You can deposit reserves into the pool using supply():

Supply USDt
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'

const tx = await aave.supply({ token: USDT, amount: 1000000n })
console.log('Supply tx hash:', tx.hash)

Withdraw

You can remove supplied liquidity using withdraw():

Withdraw USDt
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'

const tx = await aave.withdraw({ token: USDT, amount: 1000000n })
console.log('Withdraw tx hash:', tx.hash)

Borrow

You can draw debt against your collateral using borrow():

Borrow USDt
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'

const tx = await aave.borrow({ token: USDT, amount: 1000000n })
console.log('Borrow tx hash:', tx.hash)

Repay

Repayment also requires sufficient token allowance to the Aave Pool. Complete any approval before calling repay(); it is a separate transaction from repayment.

You can pay down debt using repay():

Repay USDt
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'

const tx = await aave.repay({ token: USDT, amount: 1000000n })
console.log('Repay tx hash:', tx.hash)

Quotes before sending

Quote fees use the wallet account's fee denomination: native wei for standard EVM/native-coin fees, paymaster-token base units for token-paid fees, or zero for sponsored quotes. Supply and repayment quotes assume any required approval is already in place; they do not include a separate approval's cost.

You can estimate the supply fee with quoteSupply():

Quote supply fee
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'

const supplyQuote = await aave.quoteSupply({ token: USDT, amount: 1000000n })
console.log('Supply fee (account units):', supplyQuote.fee)

You can estimate the withdraw fee with quoteWithdraw():

Quote withdraw fee
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'

const withdrawQuote = await aave.quoteWithdraw({ token: USDT, amount: 1000000n })
console.log('Withdraw fee (account units):', withdrawQuote.fee)

You can estimate the borrow fee with quoteBorrow():

Quote borrow fee
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'

const borrowQuote = await aave.quoteBorrow({ token: USDT, amount: 1000000n })
console.log('Borrow fee (account units):', borrowQuote.fee)

You can estimate the repay fee with quoteRepay():

Quote repay fee
const USDT = '0xdAC17F958D2ee523a2206206994597C13D831ec7'

const repayQuote = await aave.quoteRepay({ token: USDT, amount: 1000000n })
console.log('Repay fee (account units):', repayQuote.fee)

Health factor and collateralization limits still apply. A quote does not guarantee the transaction will succeed if on-chain state changes.

ERC-4337 smart accounts

You can run the same methods through WalletAccountEvmErc4337 and pass the optional config argument to override per-call gas payment settings. The lending methods accept the same override families as the wallet module: paymaster token, sponsorship policy, and native coins. Standard WDK EVM accounts ignore these wallet fields; compatible wrappers determine their own handling. See the ERC-4337 config override section for the full field list.

Supply with paymaster
import { WalletAccountEvmErc4337 } from '@tetherto/wdk-wallet-evm-erc-4337'
import AaveProtocolEvm from '@tetherto/wdk-protocol-lending-aave-evm'

const aa = new WalletAccountEvmErc4337(seedPhrase, "0'/0/0", {
  chainId: 1,
  provider: 'https://ethereum-rpc.publicnode.com',
  bundlerUrl: process.env.BUNDLER_URL,
  paymasterUrl: process.env.PAYMASTER_URL,
  paymasterAddress: process.env.PAYMASTER_ADDRESS,
  safeModulesVersion: '0.3.0',
  paymasterToken: {
    address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
  }
})

const aaveAA = new AaveProtocolEvm(aa)

const result = await aaveAA.supply(
  { token: '0xdAC17F958D2ee523a2206206994597C13D831ec7', amount: 1000000n },
  {
    paymasterToken: {
      address: '0xdAC17F958D2ee523a2206206994597C13D831ec7'
    }
  }
)
console.log('Supply hash:', result.hash)

safeModulesVersion is required for smart account initialization. For paymaster-token mode, set PAYMASTER_ADDRESS to the paymaster contract deployed for the selected service and chain; it tells the wallet which contract charges the configured paymaster token. Do not substitute an address from another provider or network.

You can use the same second argument to:

  • override paymaster-token mode with paymasterUrl, paymasterAddress, paymasterToken, or transferMaxFee
  • switch one call to sponsorship mode with isSponsored, paymasterUrl, and sponsorshipPolicyId
  • switch one call to native-coin gas mode with useNativeCoins and transferMaxFee

Use token addresses that exist on the same chain as the smart account RPC.

Reading account data

You can inspect collateral, debt, and health using getAccountData():

Read Aave account data
const data = await aave.getAccountData()

console.log({
  totalCollateralBase: data.totalCollateralBase,
  totalDebtBase: data.totalDebtBase,
  availableBorrowsBase: data.availableBorrowsBase,
  currentLiquidationThreshold: data.currentLiquidationThreshold,
  ltv: data.ltv,
  healthFactor: data.healthFactor
})

Next Steps

On this page