Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

Welcome to Incentra - a reliable, secure, and verifiable incentive distribution platform for DeFi protocols powered by Brevis zkCoprocessor. Incentra is designed to connect protocols with liquidity providers and individual users, and to incentivize liquidity provision, token holding and many other interactions with the protocols. It may help to achieve massive success in increasing the TVL and other forms of user proactivity and engagement with the protocols.

Why Use Incentra

  • Powered by Brevis zkCoprocessor, rewards are calculated directly in the ZK circuits and directly verified on-chain, ensuring trustless, transparent and verifiable reward computation. Users can independently verify reward amounts without relying on any centralized authority.
  • Backed by Incentra’s reliable SLA that guarantees 99.9% uptime, ensuring minimal disruptions and maximum reliability.

For Incentive Providers

  • Sustainable Growth—Incentivize users’ continuous interactions with the protocol and boost user engagement.
  • Built for Compliance—Eliminate the risks of centralized fund distribution with a fully on-chain, autonomous reward claim system, ensuring security and compliance at every step.
  • Effortless Campaign Management–Quickly and easily launch your incentive campaigns in just a few clicks with no engineering required.
  • Transparent and Trustless Incentives—Leverage ZKPs to ensure a fully transparent and trustless reward calculation and distribution process, eliminating dependence on any centralized authority or manual intervention.
  • Cross-chain Capability—Allow incentivizing actions on one blockchain while distributing rewards on another, powered by the cross-chain capability of Brevis zkCoprocessor, which allows ZKPs to be verified on any preferred chain.
  • High Flexibility—Flexible and adaptable to a wide range of incentive models, with more customization options available soon.
  • Access Controls—Restrict eligibility based on address for compliance reasons and preventing scammers.
  • Smart Rewards Forwarding—Automatically detect EOA addresses and smart contracts to ensure rewards are distributed correctly, even when LPs interact through third-party contracts like ALM.
  • Seamless Integration—Easily integrate the Incentra SDKs for campaigns and rewards data, or use the Incentra Portal as a ready-to-use interface.

For Users and LPs

  • Transparent Rewards—Reward calculations are based on ZKPs, allowing users to independently verify reward amounts without relying on a centralized authority.
  • No Added Risks—Retain liquidity or token holding while earning rewards without needing to lock up assets or added risks.
  • Earn Rewards Easily—Through one single user-friendly interface to participate in campaigns, view total rewards for all eligible campaigns, and easily claim rewards in one single transaction.
  • Gas-Efficient—Batch claim rewards in a single transaction, saving on gas fees.

Campaign Types

Incentra is designed to be flexible and adaptable across a wide range of incentive models, including:

Incentra also plans to expand into additional use cases that may be available in future phases. Feel free to contact us if you would like to create a different type of campaign or customize one to fit your specific needs.

Token Holding Campaigns

For a token holding campaign on Incentra, users earn rewards based on the time-weighted average (TWA) balance of a specified ERC-20 token. Rewards are distributed proportionally to each user’s share of the total TWA balances among all eligible users.

By retrieving and calculating token holding data directly from the blockchain, Brevis periodically updates the reward data for all eligible token holders, calculates individual reward allocations, and generates ZK Proofs (ZKPs) to validate the results. These verified results are then utilized by the reward distribution smart contracts to allocate rewards to each individual holder.

The entire process is fully transparent and trustless, allowing users to independently verify their reward amounts through ZKPs while eliminating the need for manual intervention or reliance on a potentially fallible centralized party.

Incentra also provides flexibility through additional features:

  • Blacklist: Incentive providers can exclude specific addresses from receiving rewards.
  • Staking: Users who stake their tokens in external contracts (such as staking LP tokens in gauge contracts) can still receive rewards.

Note that only a selected list of whitelisted ERC-20 tokens and reward tokens are supported. Please contact us if you’d like to whitelist a token that isn’t currently available.

Concentrated Liquidity Campaigns

For a concentrated liquidity farming campaign on Incentra, liquidity providers (LPs) earn rewards proportional to the fees generated by their positions in the pool of a Concentrated Liquidity AMM DEX such as Uniswap v3.

Brevis retrieves the position data directly from the blockchain and periodically updates the reward data for all LPs. Brevis calculates individual reward distributions and then generates zero-knowledge proofs (ZKPs) to validate the correctness of these calculations. These proofs are then verified on-chain to distribute rewards to LPs accordingly.

Incentra also supports Active Liquidity Management (ALM) protocols, allowing liquidity to be provided to the incentivized pool via ALM while earning rewards. For supported ALM protocols, Incentra automatically distributes rewards to their depositors based on their proportional share of the ALM vault (represented by the vault LP tokens), ensuring a seamless and efficient reward allocation process without requiring any additional user actions. In the initial scope, the following ALM protocols are supported.

Note that only a selected list of whitelisted rewards tokens and pool tokens are supported on Incentra. Please contact us if you’d like to whitelist a token that isn’t currently available.

Lend and Borrow Campaigns

Incentra supports lending and borrowing protocols to reward users for supplying collateral in a vault or borrowing from a vault.

Lend/Borrow Campaigns for Euler Finance

  • In lending campaigns, rewards are allocated based on each user’s share of the total time-weighted average (TWA) balances of the corresponding eToken among all eligible users.
  • In borrowing campaigns, rewards are allocated proportionally to each user’s share of the average debt within the vault. To accommodate the increasing debt due to interests, each user’s averaged debt is calculated using samples at random points of time spacing around 10 minutes.

Brevis fetches eToken and debt data directly from the blockchain, periodically updates balances for all eligible users, calculates individual rewards, and generates zero-knowledge proofs (ZKPs) to ensure the correctness of these calculations. These ZKPs are verified on-chain and the results will be utilized by the rewards distribution contracts to distribute rewards accordingly.

NOTE: If the user has multiple sub-accounts, the owner account will receive the rewards for all its sub-accounts.

NOTE: The underlying asset token of a vault needs to be whitelisted first before the vault can be used in a campaign. Please contact us if you’d like to whitelist an asset token that isn’t currently available.

Technical Architecture

The diagram below shows Incentra’s high-level architecture and workflow to support a campaign.

A campaign is divided into multiple epochs (e.g., 4 hours per epoch). Once a campaign is created, the Incentra server performs the following actions during each epoch:

  1. Fetches blockchain data relevant to the campaign.
  2. Sends the data to Brevis provers to generate rewards info and corresponding ZK proofs for all users.
  3. Submit the rewards info and ZK proofs to the campaign contract to update rewards on-chain.

Users (i.e., reward earners) can claim their rewards directly from the campaign contract once the rewards info has been updated on-chain.

Fee

By default, Brevis charges 3% of total rewards as the service fee for each campaign launched on Incentra.

Getting Started

On Incentra, campaigns can be created and managed in the Brevis Incentra Portal. Here is a checklist before you create a campaign:

  • Whitelist your campaign creator address
  • Whitelist the tokens relevant to your campaigns
  • Check if your data source chain and reward claim chain is supported
  • Contact us if there is any reward forwarding requirements

Campaign Creator Whitelist

Before getting started, please note that your wallet address must be whitelisted first to create a campaign. While anyone can create a campaign through the smart contract, Incentra exclusively recognizes and processes those created by whitelisted addresses. Please contact us to get whitelisted.

Check Supported Chains

In the Brevis Incentra Portal, you will need to select the “data source chain” and the “reward claim chain”. Data source chain is where your protocol is deployed and reward claim chain is where your reward token is deployed.

Please contact us if you cannot find the data source chain or the reward claim chain that suits your needs. We are happy to add for your requirements.

Token Whitelist

All tokens need to be first whitelisted before they can be configured in the Brevis Incentra Portal, including:

  • Reward token in campaign types
  • Underlying asset token of an Euler vault in a Lend/Borrow campaign (Euler).
  • DEX pool token 0/token 1 in a Concentrated Liquidity campaign.
  • Token to be held in a Token Holding campaign

Campaign creators can contact us to whitelist the relevant tokens.

Reward Forwarding Requirements

If your campaign requires advanced reward forwarding, please contact us for support. Common reward forwarding requirements include:

  • You would like the campaign to also incentivize users who stake their tokens into a staking contract
  • You would like to incentivize users who interact with your protocol with some intermediary such as Active Liquidity Management solutions (e.g., Beefy, Gamma).

Next Steps

The following sections offer step-by-step instructions to guide you through creating different types of campaigns:

Token Holding Campaign

Click “Create a new campaign” to create a campaign, and select the Campaign Type you would like to create.

To create a Token Holding campaign, you need to config the following info:

  • Campaign Name
  • Protocol Name and Logo
  • ERC-20 Token Info: please select the ERC-20 token you would like users to hold. Only a selected list of tokens is supported. Please contact us if you’d like to whitelist a token that isn’t currently available

  • Campaign Start Time and End Time: select the start time and end time, you could also select to set a 7-day/14-day/30-day/90-day campaign and the campaign end time will be displayed automatically
  • Blacklist Address List: it is optional to exclude specific addresses from receiving rewards
  • Select Reward Token: select the token you would like to use as a reward token and enter the total rewards amount. Only a selected list of reward tokens is supported. Please contact us if you’d like to whitelist a token that isn’t currently available
  • URL: enter the URL of the dApp where users could get the ERC-20 token

Once all the required information is provided, you can click the ‘Create Campaign’ button to confirm the campaign settings.

Please review and confirm your campaign settings before launching the campaign as the configs cannot be changed after creation.

Once the campaign settings are submitted, the campaign will be created.

You would see a pop-up with a campaign ID and view the campaign creation tx hash in explorer, confirming that your campaign has been successfully created.

You may also see the campaign creation is failed or campaign is creating, and could retry the campaign creation in the campaign page.

Note: To deposit rewards, you may also directly transfer reward tokens to the campaign contract via a simple ERC-20 transfer from a different address (e.g., a multi-sig) later.

Once the campaign is created, please deposit the rewards into the reward contract to enable reward distribution. You may deposit rewards while the campaign is to be started, active, or even ended. By default, the total rewards amount should be deposited.

Once the reward tokens are deposited, congratulations — you’re all set!

Concentrated Liquidity Campaign

Click “Create a new campaign” to create a campaign, and select the Campaign Type you would like to create.

To create a Concentrated Liquidity campaign, you need to config the following info:

  • Campaign Name
  • Dex
  • Liquidity Pool: select the chain where the pool is deployed, enter the pool address and the pool name

  • Campaign Start Time and End Time: select the start time and end time, you could also select to set a 7-day/14-day/30-day/90-day campaign and the campaign end time will be displayed automatically
  • Blacklist Address List: it is optional to exclude specific addresses from receiving rewards
  • Select Reward Token: select the token you would like to use as a reward token and enter the total rewards amount. Only a selected list of reward tokens is supported. Please contact us if you’d like to whitelist a token that isn’t currently available
  • URL: enter the URL of the dApp where LPs could deposit liquidity

Once all the required information is provided, you can click the ‘Create Campaign’ button to confirm the campaign settings.

Please review and confirm your campaign settings before launching the campaign as the configs cannot be changed after creation.

Once the campaign settings are submitted, the campaign will be created.

You would see a pop-up with a campaign ID and view the campaign creation tx hash in explorer, confirming that your campaign has been successfully created.

You may also see the campaign creation is failed or campaign is creating, and could retry the campaign creation in the campaign page.

Note: To deposit rewards, you may also directly transfer reward tokens to the campaign contract via a simple ERC-20 transfer from a different address (e.g., a multi-sig) later.

Once the campaign is created, please deposit the rewards into the reward contract to enable reward distribution. You may deposit rewards while the campaign is to be started, active, or even ended. By default, the total rewards amount should be deposited.

Once the reward tokens are deposited, congratulations — you’re all set!

Lend and Borrow Campaign (Euler)

Click “Create a new campaign” to create a campaign, and select the Campaign Type you would like to create.

Select Euler as the lending protocol to be incentivized.

To create a Euler campaign, you need to configure the following info:

  • Campaign Name
  • Action: the action you would like to incentivize - supply to a vault or borrow from a vault
  • Vault Info: select the chain where the vault is deployed and enter the vault address. The vault information should be displayed automatically

  • Campaign Start Time and End Time: select the start time and end time, you could also select to set a 7-day/14-day/30-day/90-day campaign and the campaign end time will be displayed automatically
  • Blacklist Address List: it is optional to exclude specific addresses from receiving rewards
  • Select Reward Token: select the token you would like to use as a reward token and enter the total rewards amount. Only a selected list of reward tokens is supported. Please contact us if you’d like to whitelist a token that isn’t currently available
  • URL: enter the URL of the dApp where users could supply or borrow

Once all the required information is provided, you can click the ‘Create Campaign’ button to confirm the campaign settings.

Please review and confirm your campaign settings before launching the campaign as the configs cannot be changed after creation.

Once the campaign settings are submitted, the campaign will be created.

You would see a pop-up with a campaign ID and view the campaign creation tx hash in explorer, confirming that your campaign has been successfully created.

You may also see the campaign creation is failed or campaign is creating, and could retry the campaign creation in the campaign page.

Note: To deposit rewards, you may also directly transfer reward tokens to the campaign contract via a simple ERC-20 transfer from a different address (e.g., a multi-sig) later.

Once the campaign is created, please deposit the rewards into the reward contract to enable reward distribution. You may deposit rewards while the campaign is to be started, active, or even ended. By default, the total rewards amount should be deposited.

Once the reward tokens are deposited, congratulations — you’re all set!

Campaign Rules

Common Rules

Below is the description of rules that apply to all campaign types.

Epoch

All users’ rewards are attested and updated periodically. The current period is 4 hours. Users might see their rewards updated slightly longer (e.g., 30 minutes) than 4 hours due to the time to generate ZK proofs for users’ rewards.

Also, for the 1st epoch after the campaign starts, it may take significantly more time (4 to 12 hours) to update the rewards due to the time to index and fetch relevant historical on-chain data (events, storage, transactions).

In some rare cases (e.g., there is a spike in campaign participants), the rewards update delay may be significantly longer than 4 hours as we expand system capacity and resolve the issues. Rest assured that the rewards in the delayed epochs will still be proved.

Dust Rewards

For each epoch, if a user’s rewards < $0.0001 in the epoch, the user’s rewards won’t be attested for the epoch.

Reward Rules for Each Campaign Types

Concentrated Liquidity Campaign

In a concentrated liquidity campaign, each liquidity provider (LP) is allocated rewards proportional to the fees earned:

LP campaign reward in an epoch = fees earned by LP in the epoch / total fees earned by all LPs in the epoch * total campaign rewards in the epoch * (100% - campaign fee)

Here, campaign fee is the percentage of fees charged by the Incentra platform.

NOTE: If there is no swap during an epoch, this epoch will be skipped and no LPs will get rewards for this empty epoch.

Token Holding Campaign

In a token holding campaign, each token holder is allocated rewards proportional to the Time-Weighted Averaged (TWA) token balance in the epoch:

user campaign reward in an epoch = TWA of the user in the epoch / sum of TWAs of all users in the epoch * total campaign rewards in the epoch * (100% - campaign fee)

Here, campaign fee is the percentage of fees charged by the Incentra platform.

NOTE: A user needs to directly hold the token in the wallet to receive the campaign rewards unless explicitly specified (e.g., if specified, staking the token into a staking contract may also earn rewards even if the token is not directly held in the wallet).

Lend/Borrow Campaign (Euler)

In an Euler supply campaign, each supplier is allocated rewards proportional to the Time-Weighted Averaged (TWA) eToken balance for the vault in the epoch:

user campaign reward in an epoch = eToken TWA of the user in the epoch / sum of eToken TWAs of all users in the epoch * total campaign rewards in the epoch * (1 - campaign fee)

Here, campaign fee is the percentage of fees charged by the Incentra platform.

In an Euler borrow campaign, each borrower is allocated rewards proportional to the average debt (dToken balance) for t he vault in the epoch:

user campaign reward in an epoch = user’s average debt in the epoch / sum of average debts of all users in the epoch * total campaign rewards in the epoch * (100% - campaign fee)

The average debt is calculated using samples at random points of time every 10 minutes in order to accommodate the increasing debt due to interests.

NOTE: If the user has multiple sub-accounts, the owner account will receive the rewards for all its sub-accounts.

User Tutorials

Welcome to Brevis Incentra — https://incentra.brevis.network/ — for participating in incentive campaigns and claim your rewards. To earn and claim rewards on Incentra, you will need to connect your wallet first.

Discover Campaigns

By default, you will see the “Earn” page, which lists all available campaigns on Incentra. By clicking on each row, you can view details of the active campaigns and access the URL to participate and start earning right away!

Dashboard

On the Dashboard page, you can view your claimable rewards and see all campaigns you’ve participated in—whether still active or ended with unclaimed rewards. Please note that rewards can be claimed anytime within 180 days after a campaign ends.

You can either click the ‘Claim All’ button to collect all rewards on the same chain in one single transaction, or click the ‘Claim’ button next to each campaign to claim them individually.

Guidelines

Incentra provides off-chain and on-chain APIs to fetch campaign data and let users claim their rewards. Incentive distributors can leverage these APIs to integrate Incentra with their own frontend UI to provide a seamless reward experience for users.

Specifically, the following APIs are available:

  • Get Campaign: APIs for retrieve campaigns details by different criteria (e.g., by chain, by protocol, by campaign ID, by user).
  • Read and Claim Rewards: on-chain interfaces for fetching and claiming a user’s claimable rewards.
  • Get User Leaderboard: APIs for retrieving all users and their cumulative rewards by campaign ID.

Get Campaigns

Incentra provides restful APIs to access the campaign data.

Core Functionality

The SDK provides details about different types of incentive campaigns launched on Incentra:

  1. Concentrated Liquidity Campaigns - Incentivize providing concentrated liquidity in DEXes.
  2. Token Holding Campaigns - Incentivize holding specific tokens.
  3. Lend and Borrow Campaigns (Euler) - Incentivize lending or borrowing from Euler finance.

Concentrated Liquidity Campaign

This page provides a detailed reference for the GetLiquidityCampaigns API, which allows you to retrieve information about concentrated liquidity campaigns for DEXes.

Endpoint

POST https://incentra-prd.brevis.network/sdk/v1/liquidityCampaigns

Request

FieldTypeDescription
chain_id[uint64]Filter by the chain ID(s) where the targeted DEX pool is deployed.
campaign_type[CampaignType]Filter by the DEX protocols. Enum will be specified later.
pool_id[string]Filter by pool identifier (e.g., pool address or ID).
campaign_id[string]Filter by specific campaign ID(s).
status[CampaignStatus]Filter by campaign status(es). Enum will be specified later.
user_address[string]Retrieve campaigns where the specified user address(es) has participated.

If any filter is not specified, it means there is no constraint for this filter.

CampaignType Enum

The CampaignType enum has the following values:

  • UNISWAP_V3
  • UNISWAP_V4
  • PANCAKESWAP_V3
  • PANCAKESWAP_V4
  • QUICKSWAP_V3


CampaignStatus Enum

The CampaignStatus enum has the following values:

  • DEPLOYING
  • CREATING_FAILED
  • INACTIVE
  • ACTIVE
  • ENDED
  • DEACTIVATED

Response

FieldTypeDescription
errErrMsgError details if the request failed.
campaigns[LiquidityCampaignInfo]List of matching liquidity campaigns.

LiquidityCampaignInfo Fields

Each campaign includes the following fields:

FileldTypeDescription
chain_iduint64Chain ID where the liquidity pool is deployed.
campaign_typeCampaignTypeThe DEX protocol/version for the campaign.
poolsPoolInfoInformation about the specific liquidity pool targeted by the campaign.
campaign_idstringUnique identifier for the campaign.
campaign_namestringCampaign display name.
start_timeuint64Campaign start timestamp.
end_timeuint64Campaign end timestamp.
reward_infoRewardInfoDetails about the reward token and amount. See RewardInfo below.
last_reward_attestation_timeuint64Last campaign reward attestation timestamp.
statusCampaignStatusCurrent status of the campaign. See CampaignStatus enum.

PoolInfo Fields

FieldTypeDescription
pool_idstringPool identifier (e.g., pool address or pool ID).
pool_namestringPool display name.

RewardInfo Fields

FieldTypeDescription
submission_chain_iduint64Campaign reward submission chain ID (see on-chain reward claim for details).
submission_contractstringCampaign reward submission contract address (see on-chain reward claim for details)
claim_chain_iduint64Chain ID where rewards can be claimed.
claim_contractstringSmart contract address for claiming rewards.
token_addressstringReward token address.
token_symbolstringReward token symbol.
reward_amtstringTotal reward amount for the campaign.
reward_usd_pricestringUSD price per reward token.
reward_per_hourstringReward amount distributed per hour.
aprfloatThe APR of the campaign (for example, 0.03 means 3% APR)
tvlfloatThe TVL of the liquidity pool (in USD value)

Example Request (curl)

{
    "chain_id": [
        1,
        42161
    ],
    "campaign_type": [
        1,
        2,
        3,
        4,
        5
    ],
    "pool_id": [
        "0xD0A4c8A1a14530C7C9EfDaD0BA37E8cF4204d230"
    ],
    "campaign_id": [],
    "status": [
        4,
        5
    ],
    "user_address": [] // no constraint for this filter 
}

Post with data.json

curl -X POST -H "Content-Type: application/json" -d @data.json https://incentra-prd.brevis.network/sdk/v1/liquidityCampaigns

Token Holding Campaign

This page provides a detailed reference for the GetTokenHoldingCampaigns API, which allows you to retrieve information about token holding campaigns by different filters.

Endpoint

POST https://incentra-prd.brevis.network/sdk/v1/tokenholdingCampaigns

Request

FieldTypeDescription
chain_id[uint64]Chain ID(s) where the target token is deployed.
token_address[string]Filter by the address(es) of the token being held for the campaign.
campaign_id[string]Filter by specific campaign ID(s).
status[CampaignStatus]Filter by campaign status(es). Enum will be specified later.
user_address[string]Retrieve campaigns where the specified user address(es) has participated.

If any filter is not specified, it means there is no constraint for this filter.

CampaignStatus Enum

The CampaignStatus enum has the following values:

  • DEPLOYING
  • CREATING_FAILED
  • INACTIVE
  • ACTIVE
  • ENDED
  • DEACTIVATED

Response

FieldTypeDescription
errErrMsgError message.
campaigns[TokenHoldingCampaignInfo]List of matching token holding campaigns.

TokenHoldingCampaignInfo Fields

FieldTypeDescription
chain_iduint64Chain ID where the target token is deployed.
token_addressstringAddress of the token being held.
token_symbolstringSymbol of the token being held (e.g., "WETH", "USDC").
campaign_idstringCampaign ID.
campaign_namestringCampaign display name.
start_timeuint64Campaign start timestamp.
end_timeuint64Campaign end timestamp.
reward_infoRewardInfoDetails about the reward token and amount. See RewardInfo below.
last_reward_attestation_timeuint64Timestamp of the last reward calculation/snapshot.
statusCampaignStatusCurrent status of the campaign. See CampaignStatus enum.

RewardInfo Fields

FieldTypeDescription
submission_chain_iduint64Campaign reward submission chain ID (see on-chain reward claim for details)
submission_contractstringCampaign reward submission contract address (see on-chain reward claim for details)
claim_chain_iduint64Chain ID where rewards can be claimed.
claim_contractstringAddress of the smart contract used for claiming rewards.
token_addressstringAddress of the reward token.
token_symbolstringSymbol of the reward token (e.g., "WETH").
reward_amtstringTotal reward amount for this campaign.
reward_usd_pricestringUSD price for the reward token.
reward_per_hourstringReward amount distributed per hour.
aprfloatThe APR of the campaign (for example, 0.03 means 3% APR)
tvlfloatThe total supply USD value of the token to be held

Example Request (curl)

{
    "chain_id": [
        1,
        42161
    ],
    "token_address": [
        "0x8D983cb9388EaC77af0474fA441C4815500Cb7BB"
    ],
    "campaign_id": [

    ],
    "status": [
        4,
        5
    ],
    "user_address": [

    ]
}

post with data.json

curl -X POST -H "Content-Type: application/json" -d @data.json https://incentra-prd.brevis.network/sdk/v1/tokenholdingCampaignsityCampaigns

Lend and Borrow Campaign (Euler)

This page specifies the API for retrieving details about Lend/Borrow campaigns for the Euler protocol.

Endpoint

POST https://incentra-prd.brevis.network/sdk/v1/eulerCampaigns

Request

FieldTypeDescription
chain_id[uint64]Chain ID(s) where the targeted Euler vault is deployed.
vault_address[string]List of targeted Euler vault contract addresses.
action[uint64]Filter by campaign action type: borrow: 2001, lend: 2002.
campaign_id[string]List of specific campaign IDs to retrieve.
status[CampaignStatus]Filter by campaign status (enum will be specified later)
user_address[string]Retrieve campaigns where the specified user address(es) has participated.

If any filter is not specified, it means there is no constraint for this filter.

CampaignStatus Enum

The CampaignStatus enum has the following values:

  • DEPLOYING
  • CREATING_FAILED
  • INACTIVE
  • ACTIVE
  • ENDED
  • DEACTIVATED

Response

FieldTypeDescription
errErrMsgError message if request fails.
campaigns[EulerCampaignInfo]List of Euler campaign details.

EulerCampaignInfo Fields

FieldTypeDescription
chain_iduint64Chain ID where the targeted Euler vault is deployed.
vault_addressstringEuler vault address.
actionuint64Campaign action type: borrow: 2001, lend: 2002.
campaign_idstringUnique identifier for the campaign.
campaign_namestringCampaign display name
start_timeuint64Campaign start timestamp.
end_timeuint64Campaign end timestamp.
reward_infoRewardInfoDetails about the reward token and amount. See RewardInfo below.
last_reward_attestation_timeuint64Last campaign reward attestation timestamp.
statusCampaignStatusCurrent status of the campaign. See CampaignStatus enum.

RewardInfo Fields

FieldTypeDescription
submission_chain_iduint64Campaign reward submission chain ID (see on-chain reward claim for details).
submission_contractstringCampaign reward submission contract address (see on-chain reward claim for details)
claim_chain_iduint64Chain ID where rewards can be claimed.
claim_contractstringReward claim contract address.
token_addressstringReward token address.
token_symbolstringReward token symbol.
reward_amtstringReward amount.
reward_usd_pricestringUSD price for the reward token.
reward_per_hourstringReward amount distributed per hour.
aprfloatThe APR of the campaign (for example, 0.03 means 3% APR)
tvlfloatThe supply/borrow USD value of the vault

Post Example (curl)

{
    "chain_id": [
        1,
        42161
    ],
    "vault_address": [
        "0xF037eeEBA7729c39114B9711c75FbccCa4A343C8"
    ],
    "campaign_id": [

    ],
    "status": [
        4
    ],
    "user_address": [],
    "action": [
        2001,
        2002
    ]
}

post with data.json:

curl -X POST -H "Content-Type: application/json" -d @data.json POST https://incentra-prd.brevis.network/sdk/v1/eulerCampaigns

Read and Claim Rewards

Same-chain reward claim

If the ZK-attested rewards information is submitted to the same chain that hosts the campaign for users to claim rewards, the reward claim process is straightforward: call the following functions.

// claim reward, send reward token to the earner
function claim(address earner) external;

// claim reward, send reward token to address specified by the earner (msg.sender)
function claimWithRecipient(address to) external;

One can obtain a user’s cumulative rewards and unclaimed rewards through the following view functions.

struct AddrAmt {
    address token;
    uint256 amount;
}

// get cumulative rewards
function viewTotalRewards(address user) external view returns (AddrAmt[] memory) ;
// get unclaimed rewards
function viewUnclaimedRewards(address earner) external view returns (AddrAmt[] memory);

Cross-chain reward claim

To reduce the gas cost of the campaign on an expensive chain (e.g., Ethereum), we can configure the system to submit ZK-attested rewards on a more affordable chain (e.g., Optimism, Arbitrum), then bridge the Merkle root of all rewards back to the campaign chain.

In this case, there are 2 contracts:

  1. Rewards Submission contract where the ZK-proved rewards are submitted. The Rewards Submission contract builds and stores the entire reward Merkle tree.
  2. Rewards Claim contract that synchronizes the Merkle root from the Rewards Submission contract. Users interact with this contract to claim their rewards by providing a Merkle proof. This contract also escrows the rewards and stores each user’s already-claimed reward amount.

To claim rewards, the user needs to

  1. Obtain the reward information along with the Merkle proof by calling the Get Reward Merkle Proof API.
  2. Submit the reward information along with the Merkle proof to the Reward Claim contract.

NOTE: There is also a “ClaimAll” contract which can help claim a user’s rewards from multiple campaigns in a single transaction. See here for details.

// claim reward, send reward token to the earner
function claim(
    address earner, 
    uint256[] calldata cumulativeAmounts, 
    uint64 epoch, 
    bytes32[] calldata proof) external;

// claim reward, send reward token to address specified by the earner (msg.sender)    
function claimWithRecipient(
    address to,
    uint256[] calldata cumulativeAmounts,
    uint64 _epoch,
    bytes32[] calldata proof
) external

To get a user’s claimable reward amount:

A user’s currently claimable reward amount and the cumulative reward amount can be obtained by calling the Get Reward Merkle Proof API (enclosed together with the Merkle proof) or Get Reward Balance API (an API dedicated to display a user’s reward balances).

Get Reward Merkle Proof API

This API returns the reward info and the corresponding Merkle proofs of a specific user in multiple campaigns that the user has participated in (i.e., has non-zero cumulative rewards in the campaign) and match the supplied filters in the request. The data included in the response can be used to call the claim or claimWithRecipient functions of the claim chain contract.

Endpoint

POST https://incentra-prd.brevis.network/v1/getMerkleProofsBatch

Request Fields

The request data should specify a user address and multiple filters for the campaign.

NOTE: user_addr is a required field while other filters are optional. If any filter is not specified in the request, it means no constraint for the filter.

FieldType Description
user_addrstringThe user address.
types[CampaignType]The campaign types (the detailed enum will be specified later).
chain_id[uint64]The chain IDs where the DEX pools/Euler vaults/tokens are deployed.
status[CampaignStatus]

The campaign statuses with enum:
INACTIVE = 3

ACTIVE = 4

ENDED = 5

campaign_id[string]The campaign IDs.

CampaignType enum:

  • Liquidity campaign (Uniswap v3) = 1
  • Liquidity campaign (PancakeSwap v3) = 3
  • Liquidity campaign (QuickSwap v3) = 5
  • Token holding campaign = 1001
  • Euler borrow campaign = 2001
  • Euler lend campaign = 2002

Response Fields

FieldType Description
errErrMsgError details if the request failed.
rewardsBatch[SingleCampaignMerkle]An array that includes the details about rewards info and the corresponding Merkle proofs of the user in all the campaigns that user has participated in and match the filters.

ErrMsg Fields

FieldTypeDescription
codestringError code
msgstringError reason

SingleCampaignMerkle Fields

FileldTypeDescription
campaignIdstringThe campaign ID.
epochstringThe rewards in the Merkle tree is accumulated up to this epoch number.
claimChainIdstringThe claim chain ID.
claimContractAddrstringThe claim contract address.
cumulativeRewards[string]The cumulative reward amount earned by the user in the campaign so far.
merkleProof[string]The Merkle path proof to be submitted to the claim contract.
claimableRewardsstringThe claimable reward amount of this user in the campaign.

Example Request (curl)

curl --location 'https://incentra-prd.brevis.network/v1/getMerkleProofsBatch' \
--header 'Content-Type: application/json' \
--data '{
    "user_addr": "0x0195b198088e464103e3840f52a1fa9ea81de84b",
    "types": [
        1001
    ],
    "chain_id": [
        1
    ],
    "status": [],
    "campaign_id": []
}'

Get Reward Balance API

This API returns the cumulative and claimable reward balances of a specific user in all campaigns the user has participated in and match the specified filters.

Endpoint

POST https://incentra-prd.brevis.network/v1/getUserRewardsBatch

Request Fields

The request data should specify a user address and multiple filters for the campaign.

NOTE: user_addr is a required field while other filters are optional. If any filter is not specified in the request, it means no constraint for the filter.

FieldType Description
user_addrstringThe user address.
types[CampaignType]The campaign types (the detailed enum will be specified later).
chain_id[uint64]The chain IDs where the DEX pools/Euler vaults/tokens are deployed.
status[CampaignStatus]

The campaign statuses with enum:
INACTIVE = 3

ACTIVE = 4

ENDED = 5

campaign_id[string]The campaign IDs.

CampaignType enum:

  • Liquidity campaign (Uniswap v3) = 1
  • Liquidity campaign (PancakeSwap v3) = 3
  • Liquidity campaign (QuickSwap v3) = 5
  • Token holding campaign = 1001
  • Euler borrow campaign = 2001
  • Euler lend campaign = 2002

Response Fields

FieldType Description
errErrMsgError details if the request failed.
rewardsBatch[SingleCampaignReward]An array that contains the reward balances of the user in all the campaigns that user has participated in and match the filters.

ErrMsg Fields

FieldTypeDescription
codestringError code.
msgstringError reason.

SingleCampaignReward Fields

FileldTypeDescription
cumulativestringThe cumulative reward amount earned by the user in the campaign.
claimablestringThe claimable reward amount of the user in the campaign.
campaignIdstringThe campaign ID.
claimChainIdstringThe claim chain ID.

Example Request (curl)

curl --location 'https://incentra-prd.brevis.network/v1/getUserRewardsBatch' \
--header 'Content-Type: application/json' \
--data '{
    "user_addr": "0x0195b198088e464103e3840f52a1fa9ea81de84b",
    "types": [
        1001
    ],
    "chain_id": [
        1
    ],
    "status": [],
    "campaign_id": []
}'

Claim all rewards in a single transaction

A user can claim all rewards from all participated campaigns on a given chain in a single transaction by calling the following functions of the ClaimAll contract deployed on that chain:

// claim all same-chain rewards
function claimAll(address earner, address[] calldata campaignAddrs) external;

// claim all cross-chain rewards 
// calldata can be fetched using the getMerkleProofsBatch API
struct CampaignReward {
    address campaignAddr; // the campaign claim contract address
    uint256[] cumulativeAmounts;
    uint64 epoch;
    bytes32[] proof;
}
function claimAll(address earner, CampaignReward[] calldata campaignRewards) external;

// claim all same-chain and cross-chain rewards
function claimAll(
    address earner, 
    address[] calldata sameChainCampaignAddrs, 
    CampaignReward[] calldata crossChainCampaignRewards) external;

The currently deployed ClaimAll contract addresses are:

ChainClaimAll contract address
Ethereum0x39ae8501186E8F4d7b120981DDaD5db8915A6371
BNB Chain0x3704597fdE1f11E4C87423B9246b295c31bfbb8d
Arbitrum0x273d0d19eaC2861FCF6B21893AD6d71b018E25aB
World Chain0xc8c741C7C4844Cd3C4B60d8dc95DF1DC452C53c6
Arbitrum Sepolia Testnet0x8fa1Bd18F30e0b387E2f24279Eca033eb2a30327
Base Sepolia Testnet0x39ae8501186E8F4d7b120981DDaD5db8915A6371

Get User Leaderboard

Retrieve a CSV file that displays all the users who have rewards in the campaign and their cumulative rewards by a given Campaign ID.

Endpoint

GET  https://incentra-prd.brevis.network/sdk/v1/userRewards

Example (curl)

curl https://incentra-prd.brevis.network/sdk/v1/userRewards?campaign_id=1745558044

Response:

{
    "err": null,
    "url": "https://incentra-user-reward-csv.s3.us-west-2.amazonaws.com/campaign-1745985401-rewards-20250506-061050.csv"
}

CSV name rule:

campaign-{campaignID}-rewards-{dateTime}.csv
  • campaignID: The unique ID for a campaign
  • dateTime: In "YYMMDD-HHmmss" format, UTC. For example, 20250506-151050 represents 2025-05-06 15:10:50.

CSV Format

The CSV including the 2 columns, User And EarnedAmount

  • User: user address
  • EarnedAmount: the accumulated amount of reward tokens earned by each user in the campaign

The CSV table sort in descending order by Total Rewards Earned.

Supported Chains and Protocols

If you would like to create campaigns for new chains or new protocols, please contact us.

Supported Protocols

Protocol TypeCampaign TypeProtocol Name
ERC-20 TokenToken HoldingAny protocol requiring ERC-20 token holding
DEXConcentrated LiquidityUniswap v3
DEXConcentrated LiquidityPancakeSwap v3
DEXConcentrated LiquidityKoalaSwap
Lending ProtocolLend and BorrowEuler Finance

Supported Chains

  • Ethereum
  • Arbitrum
  • OP
  • Linea
  • BNB Chain
  • Base
  • World Chain
  • TAC
  • UNITS Network

Github

Incentra Contract:

https://github.com/brevis-network/incentra-contracts

Audit reports

Incentra contract audit reports:
https://github.com/brevis-network/incentra-contracts/tree/main/audit