Aave V3 Incentive Programs
Aave reserves may offer additional incentives beyond base lending rates.
Incentive Types
- Supply Incentives: Extra APR for supplying assets to reserves
- Borrow Incentives: APR discounts for borrowing from reserves
- Conditional Incentives: Bonus rewards requiring specific supply and borrow combinations
Each reserve’s incentives array contains all active incentive programs. The incentive data includes:
- APR bonuses/discounts with formatted percentages
- Reward token information (for Aave governance incentives)
- Claim links (for Merit programs)
- Conditional requirements (for complex incentives)
You can find the incentives associated with a reserve in the incentives array of the Reserve object.
interface Reserve {
// …
incentives: ReserveIncentive[];
}
type ReserveIncentive =
| MeritSupplyIncentive
| MeritBorrowIncentive
| MeritBorrowAndSupplyIncentiveCondition
| AaveSupplyIncentive
| AaveBorrowIncentive
| MerklSupplyIncentive
| MerklBorrowIncentive
| SupplyPointsIncentive
| BorrowPointsIncentive;
These incentives come from two main sources:
Merit Programs
Third-party programs that provide extra APR rewards for specific lending activities. These require separate claiming through external platforms.
Merit programs are third-party initiatives. Aave Labs does not guarantee these programs and accepts no liability for third-party rewards.
interface MeritSupplyIncentive {
__typename: "MeritSupplyIncentive";
extraSupplyApr: PercentValue;
claimLink: string;
}
interface MeritBorrowIncentive {
__typename: "MeritBorrowIncentive";
borrowAprDiscount: PercentValue;
claimLink: string;
}
interface MeritBorrowAndSupplyIncentiveCondition {
__typename: "MeritBorrowAndSupplyIncentiveCondition";
extraApr: PercentValue;
supplyToken: Currency;
borrowToken: Currency;
claimLink: string;
}
Where:
Merit: Extra APR for supplying assets to reservesSupply Incentive Merit: APR discounts for borrowing from reservesBorrow Incentive Merit: Extra APR for supplying and borrowing the specified pair of assetsBorrow And Supply Incentive Condition
For each of these types, a claim link to the ACI Merit UI is provided.
Aave Governance Rewards
Incentives set by Aave governance through the RewardsController, typically distributed in AAVE tokens or other approved reward tokens.
interface AaveSupplyIncentive {
__typename: "AaveSupplyIncentive";
extraSupplyApr: PercentValue;
rewardTokenAddress: EvmAddress;
rewardTokenSymbol: string;
}
interface AaveBorrowIncentive {
__typename: "AaveBorrowIncentive";
borrowAprDiscount: PercentValue;
rewardTokenAddress: EvmAddress;
rewardTokenSymbol: string;
}
Where:
Aave: Extra APR for supplying assets to reservesSupply Incentive Aave: APR discounts for borrowing from reservesBorrow Incentive
In both cases, the reward token address and symbol are provided.
Claim Merit Rewards
To check for and claim Merit rewards, follow these steps.
1. Fetch the Claimable Rewards
First, determine if a user has claimable rewards. Use the use hook in React, the user action in TypeScript, or the user query in GraphQL to fetch the user’s claimable rewards and the transaction to claim them.
const { data, loading, error } = useUserRewards({
user: EvmAddress,
chainId: ChainId,
});
const { data } = useUserRewards({
user: EvmAddress,
chainId: ChainId,
suspense: true,
});
Fetch the user’s claimable rewards, optionally filtered by token.
import { useUserRewards, evmAddress, chainId } from "@aave/react";
// …
const { data, loading, error } = useUserRewards({
user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"),
chainId: chainId(1),
});
if (loading) {
return <p>Loading claimable rewards…</p>;
}
if (error) {
return <p>Error: {error.message}</p>;
}
// data: UserRewards | null
import { useUserRewards, evmAddress, chainId } from "@aave/react";
// …
const { data, loading, error } = useUserRewards({
user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"),
chainId: chainId(1),
filter: {
// Filter rewards by token address
tokens: [evmAddress("0x000000000000000000000000000000000000000A")],
},
});
if (loading) {
return <p>Loading claimable rewards…</p>;
}
if (error) {
return <p>Error: {error.message}</p>;
}
// data: UserRewards | null
import { userRewards } from "@aave/client/actions";
import { evmAddress, chainId } from "@aave/client";
import { client } from "./client";
const result = await userRewards(client, {
user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"),
chainId: chainId(1),
});
if (result.isErr()) {
console.error("Merit claim rewards error:", result.error);
} else {
// result.value: UserRewards | null
console.log(result.value);
}
import { userRewards } from "@aave/client/actions";
import { evmAddress, chainId } from "@aave/client";
import { client } from "./client";
const result = await userRewards(client, {
user: evmAddress("0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"),
chainId: chainId(1),
filter: {
// Filter rewards by token address
tokens: [evmAddress("0x000000000000000000000000000000000000000A")],
},
});
if (result.isErr()) {
console.error("Merit claim rewards error:", result.error);
} else {
// result.value: UserRewards | null
console.log(result.value);
}
query {
userRewards(
request: {
user: "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234"
chainId: 1
# Optional filter
# filter: {
# tokens: ["0x000000000000000000000000000000000000000A"]
# }
}
) {
chain
claimable {
amount {
usdPerToken
usd
amount {
value
decimals
raw
}
}
currency {
address
imageUrl
name
symbol
decimals
chainId
}
}
transaction {
to
from
data
value
chainId
operation
}
}
}
The user has no claimable rewards if data is null in React, if result. is null in TypeScript, or if the query result is null in GraphQL.
2. Claim Rewards
Finally, if the user has claimable rewards, they can claim them by sending the transaction.
- React: Use the
usehook for the wallet library of your choice to sendSend Transaction data..transaction - TypeScript: Use
sendfor your chosen wallet library to send the transaction.With - GraphQL: Send the
transactionrequest directly using the wallet associated with the from address.
import { useWalletClient } from "wagmi";
import { useUserRewards } from "@aave/react";
import { useSendTransaction } from "@aave/react/viem";
// …
const { data: walletClient } = useWalletClient();
const { data } = useUserRewards({
// …
suspense: true,
});
const [sendTransaction, sending] = useSendTransaction(walletClient);
// …
const execute = async () => {
if (data !== null) {
const result = await sendTransaction(data.transaction);
if (result.isErr()) {
console.error(result.error.message);
} else {
console.log("Merit claim rewards successful with hash:", result.value);
}
}
};
import { userRewards } from "@aave/client/actions";
import { sendWith } from "@aave/client/viem";
import { client } from "./client";
import { wallet } from "./wallet";
const meritRewards = await userRewards(client, {
// …
});
if (meritRewards.isErr()) {
console.error(meritRewards.error);
process.exit(1); // or eager return if in a function
}
if (!meritRewards.value) {
console.log("No rewards to claim");
process.exit(1); // or eager return if in a function
}
const result = await sendWith(wallet)(meritRewards.value.transaction);
if (result.isErr()) {
console.error("Claiming Merit rewards failed:", result.error);
} else {
console.log("Merit rewards claimed successfully:", result.value);
}
Send transaction from the from wallet.
{
"data": {
"userRewards": {
"chain": 1,
"claimable": [
{
"amount": {
"usdPerToken": "1.000000000000000000",
"usd": "1.00",
"amount": {
"value": "1.000000000000000000",
"decimals": 18,
"raw": "1000000000000000000"
}
},
"currency": {
"address": "0x000000000000000000000000000000000000000A",
"name": "Example Token",
"symbol": "EXAMPLE",
"decimals": 18,
"chainId": 1,
"imageUrl": "https://example.com/image.png"
}
}
],
"transaction": {
"to": "0x000000000000000000000000000000000000000B",
"from": "0x742d35cc6e5c4ce3b69a2a8c7c8e5f7e9a0b1234",
"data": "0x…",
"value": "0",
"chainId": 1,
"operation": null
}
}
}
}