Incentive Programs

Learn how to discover and claim incentive rewards on Aave v4.


Aave v4 reserves may offer additional incentives beyond base lending rates. These incentives are distributed through Merkl, a decentralized incentive distribution platform.

Reward Types

Potential rewards are available in the rewards array of the Reserve Summary.

interface Reserve {  // …  summary: {    rewards: Reward[];    // …  };}
type Reward = MerklSupplyReward | MerklBorrowReward;

Supply Rewards

Supply rewards can be present on suppliable reserves and represent an extra APY on top of the base reserve supply APY.

The accrued extra interest is paid in the specified payout token when the incentive campaign reaches its maturity.

interface MerklSupplyReward {  __typename: "MerklSupplyReward";  id: string;  startDate: Date;  endDate: Date;  extraApy: PercentNumber;  payoutToken: Erc20Token;  criteria: MerklCriteria[];  userEligible: boolean;}

Where:

  • extraApy - The additional APY earned on top of the base supply APY

  • payoutToken - The token used to pay the extra interest accrued from the reward

  • criteria - Eligibility requirements for earning the reward

  • userEligible - Whether the current user meets all criteria

Borrow Rewards

Borrow rewards can be present on borrowable reserves and represent an APY discount on the user's borrow rate (which includes their Risk Premium).

The accrued interest discount is paid in the specified payout token when the incentive campaign reaches its maturity.

interface MerklBorrowReward {  __typename: "MerklBorrowReward";  id: string;  startDate: Date;  endDate: Date;  discountApy: PercentNumber;  payoutToken: Erc20Token;  criteria: MerklCriteria[];  userEligible: boolean;}

Where:

  • discountApy - The APY discount applied to the user's borrow rate

  • payoutToken - The token used to pay the reward

  • criteria - Eligibility requirements for earning the reward

  • userEligible - Whether the current user meets all criteria

Eligibility Criteria

Each reward may have eligibility criteria that users must meet.

interface MerklCriteria {  __typename: "MerklGenericCriteria";  id: string;  text: string;  userPassed: boolean;}

Where:

  • text - Human-readable description of the criterion

  • userPassed - Whether the current user meets this criterion

Matured Rewards

Rewards become claimable when their incentive campaign reaches maturity. Campaigns are often renewed upon reaching their end date, so users should check for new reward opportunities periodically.

Claimable Rewards

Fetch the user's matured rewards that are ready to claim.

Use the useUserClaimableRewards hook (or the imperative useUserClaimableRewardsAction variant) to fetch all rewards the user can claim.

import { useUserClaimableRewards, type EvmAddress } from "@aave/react";
function ClaimableRewards({ user }: { user: EvmAddress }) {  const { data, loading, error } = useUserClaimableRewards({ user });
  if (loading) return <div>Loading…</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (data.length === 0) return <div>No claimable rewards</div>;
  return (    <div>      {data.map((reward) => (        <div key={reward.id}>          <p>Amount: {reward.claimable.amount.value.toDecimalPlaces(2)}</p>          <p>Claim until: {reward.claimUntil.toLocaleDateString()}</p>        </div>      ))}    </div>  );}

The useUserClaimableRewardsAction hook does not watch for updates. Use it when you need on-demand, fresh data (e.g., in an event handler).

The UserMerklClaimableReward type contains details about each claimable reward:

interface UserMerklClaimableReward {  __typename: "UserMerklClaimableReward";  id: string;  claimable: Erc20Amount;  startDate: Date;  endDate: Date;  claimUntil: Date;}

Where:

  • id - Unique identifier for the reward (used when claiming)

  • claimable - The claimable token amount

  • startDate - When the reward period started

  • endDate - When the reward period ended

  • claimUntil - Deadline to claim the reward

Claim Rewards

Once you have claimable rewards, collect them individually or all at once in a single transaction.

After claiming, the claimable rewards list may not update immediately. The update depends on Merkl signaling that the rewards have been claimed, which can take some time.

To claim rewards 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 Claim Flow

Then, use the useClaimRewards hook to prepare the claim operation.

import { useClaimRewards } from "@aave/react";
const [claim, { loading, error }] = useClaimRewards((transaction) =>  sendTransaction(transaction),);

3

Execute the Claim Operation

Then, execute the claim operation with the reward IDs from the claimable rewards.

Claim Rewards
import { useUserClaimableRewards, rewardId, evmAddress } from "@aave/react";
const { data: claimableRewards } = useUserClaimableRewards({  user: evmAddress(wallet.account.address),  suspense: true,});
const execute = async () => {  if (claimableRewards.length > 0) {    const result = await claim({      ids: claimableRewards.map((reward) => rewardId(reward.id)),    });
    // …  }};

4

Handle the Result

Finally, handle the result.

Example
const execute = async () => {  const result = await claim(/* … */);
  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 "UnexpectedError":        console.error(result.error.message);        break;    }    return;  }
  console.log("Rewards claimed successfully with hash:", result.value);};