# Table of Contents - [Merkl Documentation Portal | Merkl Docs](#merkl-documentation-portal-merkl-docs) - [Technical Overview | Merkl Docs](#technical-overview-merkl-docs) - [Campaign Types | Merkl Docs](#campaign-types-merkl-docs) - [Lending and Borrowing Campaigns | Merkl Docs](#lending-and-borrowing-campaigns-merkl-docs) - [Concentrated Liquidity Campaigns | Merkl Docs](#concentrated-liquidity-campaigns-merkl-docs) - [Incentive Mechanisms | Merkl Docs](#incentive-mechanisms-merkl-docs) - [Airdrop Campaigns | Merkl Docs](#airdrop-campaigns-merkl-docs) - [Encompassing Campaigns | Merkl Docs](#encompassing-campaigns-merkl-docs) - [Scoring Types | Merkl Docs](#scoring-types-merkl-docs) - [Staking & Restaking Campaigns | Merkl Docs](#staking-restaking-campaigns-merkl-docs) - [Token Holding Campaigns | Merkl Docs](#token-holding-campaigns-merkl-docs) - [Additional Features | Merkl Docs](#additional-features-merkl-docs) - [Create a campaign from a multisig or Gnosis Safe | Merkl Docs](#create-a-campaign-from-a-multisig-or-gnosis-safe-merkl-docs) - [Fee Model | Merkl Docs](#fee-model-merkl-docs) - [Branding and Integration | Merkl Docs](#branding-and-integration-merkl-docs) - [Before you start | Merkl Docs](#before-you-start-merkl-docs) - [Distribution Types | Merkl Docs](#distribution-types-merkl-docs) - [Glossary | Merkl Docs](#glossary-merkl-docs) - [Smart Contract Addresses | Merkl Docs](#smart-contract-addresses-merkl-docs) - [Create a campaign | Merkl Docs](#create-a-campaign-merkl-docs) - [Display Your Native APR | Merkl Docs](#display-your-native-apr-merkl-docs) - [Create a campaign pre-TGE | Merkl Docs](#create-a-campaign-pre-tge-merkl-docs) - [Create your campaign from a DAO | Merkl Docs](#create-your-campaign-from-a-dao-merkl-docs) - [Create multiple campaigns | Merkl Docs](#create-multiple-campaigns-merkl-docs) - [Merkl User FAQ | Merkl Docs](#merkl-user-faq-merkl-docs) - [Campaign Management | Merkl Docs](#campaign-management-merkl-docs) - [Reward Forwarding | Merkl Docs](#reward-forwarding-merkl-docs) - [Earn rewards - User guide | Merkl Docs](#earn-rewards-user-guide-merkl-docs) - [Campaign Configuration | Merkl Docs](#campaign-configuration-merkl-docs) - [Create a point program | Merkl Docs](#create-a-point-program-merkl-docs) - [Customization Options | Merkl Docs](#customization-options-merkl-docs) - [Integrate Merkl API | Merkl Docs](#integrate-merkl-api-merkl-docs) --- # Merkl Documentation Portal | Merkl Docs Merkl is a DeFi incentive platform that **connects liquidity providers with protocols** looking to boost activity and engagement. * For Protocols: Launch, manage, and customize growth campaigns to attract liquidity, track user engagement, and distribute incentives without the usual operational burden. * For Users: Earn rewards or points by participating in incentive campaigns. At its core, Merkl operates on an offchain engine that processes both onchain and offchain data to compute rewards and points for campaigns. [](https://docs.merkl.xyz/#what-sets-merkl-apart) What sets Merkl apart? ----------------------------------------------------------------------------- ### [](https://docs.merkl.xyz/#for-campaign-creators) For Campaign Creators * 🚀 **Launch Complex Incentives in Minutes**: Start a fully customized incentive campaign in less than 3 minutes—no need for weeks of development. * 📈 **Comprehensive Coverage**: Merkl supports incentives on top of various DeFi activities across multiple chains: * **Liquidity Incentives**: Reward LPs in concentrated (CLAMM) and constant product pools. * **Airdrops**: Retroactive token distributions based on snapshots or custom criteria. * **Lending/Borrowing**: Campaigns for lenders and borrowers of various types of lending protocols like Aave, Compound, Morpho, and more. * **Token Balance**: Reward token holders based on relative balances over time.pools. * 🛠 **Unmatched Flexibility**: Run multiple campaigns per asset with customizable distribution methods: * **Customizable Distribution Types**: Define how rewards are distributed to eligible addresses—whether through a fixed or variable reward rate that adapts to participant behavior, or via a custom, smart distribution logic tailored to your needs * **Crosschain Incentives**: Incentivize an asset on one chain while distributing rewards on another. * **Reward Boosts**: Increase rewards for users holding specific ERC20 tokens. * **Blacklist / Whitelist Controls**: Restrict eligibility based on addresses (e.g., compliance lists or protocol-specific criteria). * **Recover Unclaimed Rewards**: Reallocate unclaimed rewards to any destination of your choice, ensuring they remain effectively utilized. * **Control, Monitor, Update your Emissions**: Dynamically adjust and refine your reward campaigns even after launch, allowing you to dynamically manage incentives for maximum ROI and performance. * ⚡ **Smart Rewards Forwarding**: Automated detection of smart contracts & staking pools ensures rewards are correctly distributed even if users interact via third-party contracts. * 📊 **Advanced Analytics**: Gain deep insights into incentive performance, including reward distribution, liquidity source breakdowns, and engagement trends. * 🔌 **Effortless Integration**: Use the Merkl API for seamless data integration (APRs, rewards, analytics) or rely on the Merkl App for a ready-to-use interface.  Launch and manage your incentive campaigns in Merkl Studio ### [](https://docs.merkl.xyz/#for-users) For Users * 💰 **Maximize Earnings with Competitive APRs**: Access multiple campaigns for the same asset to stack incentives and boost returns. * 🔓 **No Staking Required**: Simply participate in eligible activities—no need to lock up assets or take on extra smart contract risks. * ⛽ **Gas-Efficient Rewards**: Batch claim rewards in a single transaction, saving gas fees. * 🌍 **A One-Stop Hub for DeFi Incentives**: With 20,000+ campaigns, Merkl provides a centralized dashboard to track earnings and discover the best opportunities. Merkl is a **non-custodial solution**. You retain full control over your assets—Merkl only processes reward claims. There is no additional smart contract risk beyond what’s already involved in your DeFi activities.  Users can explore earning opportunities and claim their rewards on the Merkl App [](https://docs.merkl.xyz/#how-to-get-started) How to get started? ----------------------------------------------------------------------- ### [](https://docs.merkl.xyz/#for-campaign-creators-1) For Campaign Creators * Learn how Merkl works under the hood by checking the [Technical Overview](https://docs.merkl.xyz/merkl-mechanisms/technical-overview) * Explore available the versatility of [Merkl Incentive Mechanisms](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms) , including its [Campaign Types](https://docs.merkl.xyz/merkl-mechanisms/campaign-types) , [Distribution Types](https://docs.merkl.xyz/merkl-mechanisms/distributions) , its [Customizability Hooks](https://docs.merkl.xyz/merkl-mechanisms/customization-options) or the [Additional Features](https://docs.merkl.xyz/merkl-mechanisms/features) it offers * Start your first campaign on [Merkl Studio](https://studio.merkl.xyz/) using our [guides](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign) * Forwarder, deposit URL, dispute,... — check the [Glossary](https://docs.merkl.xyz/merkl-mechanisms/glossary) if there's a term you don't understand. ### [](https://docs.merkl.xyz/#for-users-1) For Users * Discover active campaigns & start earning in [the Merkl App](https://app.merkl.xyz/) * Learn how to earn rewards in Merkl by checking the [user guide](https://docs.merkl.xyz/earn-with-merkl/earning-with-merkl) * Opportunity, campaign, APR,... — check the [Glossary](https://docs.merkl.xyz/merkl-mechanisms/glossary) if there's a term you don't understand. [](https://docs.merkl.xyz/#links) 🔗 Links ----------------------------------------------- * [Merkl App](https://app.merkl.xyz/) * [Merkl Studio](https://studio.merkl.xyz/) * [Merkl Website](https://merkl.xyz/) * [Twitter](https://x.com/merkl_xyz) * [Discord](https://discord.com/invite/Gs8MUrUVP3) * [Audit](https://code4rena.com/reports/2023-06-angle) [](https://docs.merkl.xyz/#contact-us) 📩 Contact Us --------------------------------------------------------- Merkl is constantly evolving with new features and integrations. If you have specific use cases (e.g., perpetual DEX incentives, borrower-specific rewards, yield aggregator campaigns), or need guidance on your incentive or points program, contact us on [Discord (BD Ticket)](https://discord.gg/jnYfrGxDbe) . [NextTechnical Overview](https://docs.merkl.xyz/merkl-mechanisms/technical-overview) Last updated 5 months ago * [What sets Merkl apart?](https://docs.merkl.xyz/#what-sets-merkl-apart) * [For Campaign Creators](https://docs.merkl.xyz/#for-campaign-creators) * [For Users](https://docs.merkl.xyz/#for-users) * [How to get started?](https://docs.merkl.xyz/#how-to-get-started) * [For Campaign Creators](https://docs.merkl.xyz/#for-campaign-creators-1) * [For Users](https://docs.merkl.xyz/#for-users-1) * [🔗 Links](https://docs.merkl.xyz/#links) * [📩 Contact Us](https://docs.merkl.xyz/#contact-us) --- # Technical Overview | Merkl Docs Merkl operates through an offchain engine that analyzes both onchain and offchain data to track user activity and allocate rewards based on campaign rules set by campaign creators. The Merkl engine processes reward data into a merkle tree, compresses it into a merkle root, and pushes it onchain, enabling users to claim rewards transparently and efficiently. [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#platform-overview) 🗺️ Platform Overview ----------------------------------------------------------------------------------------------------------- Merkl operates through campaigns created by campaign creators. A campaign is a time-bound incentive program where Merkl tracks onchain and offchain activity based on predefined rules. Rewards or points are either posted onchain or updated offchain via Merkl’s endpoints, allowing users to monitor their accumulated rewards. ### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#how-it-works) How it works 1. **Campaign Creation**: Campaign creators set up campaigns using a smart contract called the **Merkl Distribution Creator**. This includes defining eligibility criteria, reward structures, and distribution methods. Campaign details are pushed onchain, along with the incentive tokens that need to be distributed 2. **User Participation**: Users engage with the protocol (e.g., providing liquidity, lending, borrowing) in order to earn the rewards/points as specified in the campaign. 3. [**Reward Computation:**](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-computation) At fixed intervals, a system called the **Merkl Engine** fetches campaigns from the **Merkl Distribution Creator** contract and processes reward calculations based on available onchain and offchain data and on the rules set by the campaign creator. **The Merkl Engine tracking is exhaustive and does not rely on discretionary snapshots**. 4. [**Reward Update:**](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-updates) After each reward computation, users can see that they have earned **pending rewards** (awaiting onchain reward update). At regular intervals, (potentially different from the reward computation intervals), the Merkl Engine generates a merkle tree from processed campaigns. This tree is then compressed as a merkle root that is pushed onchain to a contract called the **Merkl Distributor** contract. A reward file is also made available [on the Merkl status page](https://app.merkl.xyz/status) , in order to ensure transparency and enable anyone to manually audit past reward distributions. 5. [**Dispute Period:**](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#dispute-process) After this step, a 1-2 hour dispute period begins, during which newly computed rewards cannot be claimed yet. However, rewards from the previous merkle root remain claimable. During this period, dispute bots verify the published reward file. If an inconsistency is found, a dispute can be raised to halt incorrect distributions before they become effective. 6. **Reward Availability:** Once the dispute period ends, users can see their rewards on any frontend integrated with the Merkl API. Users can claim rewards through a Merkl-powered frontend. Merkle proofs, required for claiming, are provided by the Merkl API or can be computed from reward files. ### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#key-features) Key Features * **Single Merkl Root per Chain:** Merkl consolidates rewards from multiple campaigns into one merkle root per chain, enabling efficient batch claiming rewards from multiple different campaigns in a single transaction. * **Aggregated Campaigns:** While campaigns operate independently, Merkl batches multiple campaign updates into a single onchain transaction * **Automatic Catch-Up Mechanism:** If any rewards are not included in an update, they are automatically distributed in the next cycle. The Merkl engine ensures no missed rewards, processing only the data from the previous execution point. * **Unclaimed Rewards Roll Over**: Users can claim their rewards at anytime they want: each merkle tree update takes the previous merkle tree state and simply adds the new rewards, which are then reflected in the published merkle root. [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#deep-dive) 🤿 Deep-Dive ------------------------------------------------------------------------------------------ ### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-computation) Reward Computation **Reward computation** (or "compute") is the process by which the Merkl Engine calculates reward allocations based on campaign rules. **Computation mechanism**: The Merkl Engine relies on events to reconstruct the exact position of each participant. An integral is then computed over the selected time frame for every user, with no approximations—everything is exact. Users are rewarded proportionally to their individual area under the curve compared to the total area of all participants. In rare occurrences (e.g., debt accrual in lending markets), events alone are not enough to reconstruct the exact positions (e.g., debt accrual events are only emitted when a user interacts with the market), to remedy this, the Merkl Engine keeps track of **invariants** for these protocols, it compares at regular intervals the total event-based positions of users and the onchain value (e.g., calling `totalDebt()` on a lending market). If the two values differ by more than **1%**, the Merkl Engine will check each user's position onchain to update the computed value and remain exact. **Computation frequency**: The Merkl engine processes rewards for each campaign approximately every 2 hours on average, analyzing all relevant onchain events affecting the incentivized asset. **After computation**: Once a campaign completes its computation cycle, rewards are not immediately claimable onchain but appear as **pending rewards** in user dashboards. **Parallel processing**: Campaigns on a chain are processed independently and in parallel. This means rewards from some campaigns may be available onchain while others are still computing or awaiting updates. **Delayed computations**: Occasionally, campaign computations may be delayed due to processing constraints. Track delayed campaigns on the [Merkl status page](https://app.merkl.xyz/status) . **Continuous processing**: When a campaign is processed, the Merkl Engine resumes from its last checkpoint, ensuring complete reward coverage even when updates occur at different intervals. **Reward delays & retroactive distribution** Occasional delays of a few hours may occur in reward distribution. If an invariant is triggered or a third-party data feed experiences a temporary issue, calculations are paused until all safety checks pass at the next scheduled computation. When this happens, the Merkl system is designed so that **all rewards are distributed retroactively**, with no rewards undistributed. ### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-updates) Reward Updates **Reward updates** are the process of posting computed rewards onchain, making them claimable by users. **Update frequency**: Reward updates occur approximately every 8 hours (ranging from 4 to 12 hours), depending on the chain. **Delayed updates**: Like computations, updates may occasionally be delayed. Monitor update status on the [Merkl status page](https://app.merkl.xyz/status) . **Transparency**: Each reward update includes a publicly available reward file on the status page for transparency and auditability. **Independent cycles**: Reward computation and reward updates operate on independent schedules. Updates push the results of completed computations onchain, but the two processes follow separate lifecycles. **Example**: Between two reward updates (8 hours apart on average), a campaign's rewards may be recomputed up to four times. Each computation refines the pending rewards, but they only become claimable when the next update occurs. **Rollover mechanism**: Unclaimed rewards automatically roll over into subsequent reward updates, allowing users to claim at their convenience. **Tracking updates**: View the last reward update for each chain on the [Merkl status page](https://app.merkl.xyz/status) . ### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#dispute-period-and-process) Dispute Period & Process The **dispute period** is a security window of 1-2 hours following each reward update during which anyone can contest reward allocations made by the Merkl engine. This safeguard ensures the integrity and consistency of the reward infrastructure and allows campaign creators to oversee the reward computations before they become final and claimable. **Raising a dispute**: If an issue is detected during the dispute period or if you want to contest reward allocations for a campaign, raise a dispute by sending a `disputeToken` to the Merkl Distributor contract. **Dispute outcomes**: * **Valid dispute**: The merkle root is revoked and the disputer is refunded * **Invalid dispute**: The disputer forfeits their funds and the dispute period restarts **Dispute parameters**: Retrieve dispute conditions (`disputeToken`, `disputeAmount`, `disputePeriod`) from the Distributor contract on the relevant chain. #### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#dispute-bots) Dispute Bots **Security infrastructure**: The Merkl team operates several independent dispute bots on separate infrastructure to ensure redundancy and prevent malicious actors from compromising the reward update process. **Open-source reference**: While the production bot code is closed source for security reasons, you can reference [this open-source repository](https://github.com/AngleProtocol/merkl-dispute) to understand how to build a dispute bot. **Strengthen the network**: More active dispute bots make the system more secure. Need help setting one up? Reach out to the Merkl team—we're happy to assist! [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#key-merkl-concepts) 📌 Key Merkl Concepts ------------------------------------------------------------------------------------------------------------ ### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#opportunity-vs.-campaign) Opportunity vs. Campaign Understanding the distinction between **opportunities** and **campaigns** is fundamental to how Merkl operates. * **Campaign**: An individual incentive program created by a campaign creator with specific parameters including [a distribution type](https://docs.merkl.xyz/merkl-mechanisms/distributions) , [a scoring type](https://docs.merkl.xyz/merkl-mechanisms/scoring) , [customization options](https://docs.merkl.xyz/merkl-mechanisms/customization-options) , a budget amount, and a duration. Each campaign has [a specific type](https://docs.merkl.xyz/merkl-mechanisms/campaign-types) and targets a particular onchain behavior (e.g., providing liquidity in a pool, holding a token, lending/borrowing)—this targeted behavior represents an opportunity. * **Opportunity**: A specific asset (e.g., pool, vault) and its associated action (e.g., depositing liquidity, borrowing assets) that can be incentivized. Multiple campaigns can run in parallel on a single opportunity, meaning users performing one onchain action can simultaneously earn rewards from several different campaigns. Example: _Providing liquidity to a SushiSwap V3 pool is an opportunity that may have multiple active campaigns offering different rewards._  An opportunity page with several incentive campaigns running on it ### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#main-metrics) Main Metrics The following metrics are fundamental to Merkl and appear throughout all Merkl user-facing components: the API, the app, and Merkl Studio. #### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#daily-rewards) Daily Rewards Daily rewards for a campaign represent the total amount of tokens or points distributed each day, shared among all eligible users of the campaign. While this number is typically accurate, it may be estimated for certain [distribution types](https://docs.merkl.xyz/merkl-mechanisms/distributions) (such as fixed and capped reward rates) that distribute based on the eligible TVL in the campaign. When multiple campaigns run on an opportunity, including subcampaigns, the daily rewards displayed for the opportunity represent the sum of all individual campaign daily rewards. #### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#tvl) TVL The Total Value Locked (TVL) of a campaign on Merkl represents the total value of **eligible** assets for the campaigns on the opportunity. This reflects only the assets that meet the campaign's eligibility criteria, for example: * if a campaign includes a blacklist, the TVL excludes the value held by blacklisted addresses. * for certain campaign types like net-lending campaigns, the TVL represents the net supplied TVL (i.e., total supplied minus borrowed), as this reflects only the liquidity that's eligible for rewards. In these cases, Merkl may initially approximate the TVL and requires an engine computation to display the accurate TVL for the campaign. As such, the TVL may not be accurate at launch for newly created campaigns. In some situations, the TVL might also be over- or underestimated due to approximations made for computational efficiency or because exact computing logic has not yet been implemented. When the Merkl system has a fallback mechanism, TVL values update every 10 minutes on the Merkl app and API. For complex campaigns without such fallbacks, TVLs (and consequently APRs) only update after each computation cycle. This means TVL updates may occur at most every 2 hours for the opportunities related to these campaigns. Overall, the TVL serves as a key indicator of the market or pool's size and liquidity depth. When multiple campaigns run on the same opportunity with different eligibility rules, the displayed TVL for the opportunity is **the maximum eligible TVL** across all campaigns. #### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#apr) APR The Annual Percentage Rate (APR) represents the yearly return from participating in a campaign, expressed as a percentage. Depending on the [distribution type](https://docs.merkl.xyz/merkl-mechanisms/distributions) , the APR can be fixed and remain constant throughout the campaign, or it can be variable and fluctuate based on factors such as eligible TVL and the number of participants. For [distribution types](https://docs.merkl.xyz/merkl-mechanisms/distributions) where the APR is not fixed, the APR for a campaign is calculated as: Daily Rewards×365Eligible TVL\\frac{\\text{Daily Rewards} \\times 365}{\\text{Eligible TVL}}Eligible TVLDaily Rewards×365 In these cases, the APR updates at the same frequency as the eligible TVL (every 10 minutes for simple campaigns, or every 2 hours for more complex campaigns where TVL cannot be simply approximated). At the opportunity level, the displayed APR is the sum of the APRs from all campaigns ([including subcampaigns](https://docs.merkl.xyz/merkl-mechanisms/reward-forwarding#linked-opportunities) ) running on that opportunity. [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#user-facing-components) 🧱 User-Facing Components -------------------------------------------------------------------------------------------------------------------- Beyond the Merkl engine and dispute bots, the Merkl ecosystem includes several user-facing components that work together to enable campaign creation, reward tracking, and claiming. ### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#merkl-smart-contracts) Merkl Smart Contracts Deployed on each blockchain integrated by Merkl, Merkl's smart contracts store campaign data, hold incentive tokens, and process reward claims. These contract are [publicly available](https://github.com/AngleProtocol/merkl-contracts) and have been audited by Code4rena ([Audit Report](https://code4rena.com/reports/2023-06-angle) ). Key contracts: * `DistributionCreator`: Stores campaign details and configurations. * `Distributor`: Holds tokens and processes reward claims based on merkle proofs. * `AccessControlManager`: A multisig-controlled contract that manages disputes, fees, and access control but cannot alter distributions. Smart contract addresses, categorized by chain are listed [here](https://app.merkl.xyz/status) . ### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#merkl-api) Merkl API [Merkl API](https://docs.merkl.xyz/integrate-merkl/app) provides real-time access to Merkl data, including rewards, APRs, merkle proofs, and analytics. This API enables any frontend to integrate Merkl seamlessly. ### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#merkl-app) Merkl App [The Merkl App](https://app.merkl.xyz/) , built on the Merkl API, enables users to explore reward opportunities, track APRs, and seamlessly claim their rewards.  Home page of the Merkl App The interface is organized around several types of pages: * **Home page (all opportunities)** – displays all available opportunities with filtering options * **Opportunity page** – dedicated view for each opportunity with all its campains * **Protocol / Chain / Liquidity program page** – groups all opportunities related to a specific protocol, chain, or program * **Dashboard** – where users can claim their rewards  Dashboard page where users can claim their rewards Among all these pages, the **Opportunity page** is central, as this is where you’ll find the campaigns created. Detailed info for each campaign running on an opportunity is available across several tabs: * **Overview:** global details such as dates, APR, and eligibility rules,… * **Advanced**: distribution progress, last snapshot, creator address, and campaign ID,… * **Leaderboard**: list of addresses participating in the opportunity * [**Linked opportunities**](https://docs.merkl.xyz/merkl-mechanisms/reward-forwarding#linked-opportunities) _(optional):_ displays opportunities connected through shared liquidity and rewards  Campaign-specific info on the opportunity page ### [](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#merkl-studio) Merkl Studio [Merkl Studio](https://studio.merkl.xyz/) is the command center for campaign creators. It enables anyone to launch and manage incentive campaigns independently within minutes, providing powerful tools for campaign configuration and oversight. [PreviousMerkl Documentation Portal](https://docs.merkl.xyz/) [NextIncentive Mechanisms](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms) Last updated 1 month ago * [🗺️ Platform Overview](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#platform-overview) * [How it works](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#how-it-works) * [Key Features](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#key-features) * [🤿 Deep-Dive](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#deep-dive) * [Reward Computation](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-computation) * [Reward Updates](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-updates) * [Dispute Period & Process](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#dispute-period-and-process) * [📌 Key Merkl Concepts](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#key-merkl-concepts) * [Opportunity vs. Campaign](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#opportunity-vs.-campaign) * [Main Metrics](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#main-metrics) * [🧱 User-Facing Components](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#user-facing-components) * [Merkl Smart Contracts](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#merkl-smart-contracts) * [Merkl API](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#merkl-api) * [Merkl App](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#merkl-app) * [Merkl Studio](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#merkl-studio) --- # Campaign Types | Merkl Docs [Concentrated Liquidity Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms) [Airdrop Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop) [Token Holding Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms) [Lending and Borrowing Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing) [Encompassing Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing) [Staking & Restaking Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/staking) [PreviousIncentive Mechanisms](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms) [NextConcentrated Liquidity Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms) Last updated 11 months ago --- # Lending and Borrowing Campaigns | Merkl Docs [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing#supported-protocols) 🫴🏼 Supported protocols ------------------------------------------------------------------------------------------------------------------------------ Merkl supports **most major lending and borrowing protocols**, such as Morpho, Euler, Compound, and Aave. A non-exhaustive list of supported protocols can be found in the ["Lending & Borrowing" section of Merkl Studio](https://studio.merkl.xyz/create-campaign/lend) when selecting a protocol.  Merkl natively supports **all lending and borrowing protocols that issue receipt tokens** for lenders and debt tokens for borrowers — such as Aave with aTokens. For these protocols, please use the [“Token Holding” incentive category](https://studio.merkl.xyz/create-campaign/erc20) in Merkl Studio, as you are incentivizing a token that represents a lending position. If you’d like your lending and borrowing protocol to be fully integrated and supported by Merkl — or if you're looking to create tailored protocol-specific campaigns — please reach out on the [Merkl Discord](https://discord.com/invite/jnYfrGxDbe) by opening a BD ticket to discuss the integration process. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing#preventing-lending-loops) 🔁 Preventing lending loops -------------------------------------------------------------------------------------------------------------------------------------- Merkl allows campaign creators to reward users based on their **net lending position** (lending minus borrowing) to avoid lending and borrowing loops. As a campaign creator, you have the possibility to enable net lending on a specific opportunity. When enabled, users will not get extra rewards by borrowing the same asset and re-lending it again. This is to ensure there are no infinite loops & unefficient TVL. For example, if you lend $100 wstETH and borrow $60 wstETH, you get rewarded for $40 wstETH ($100 - $60). Note: this is not always the case. If you’ve got a doubt about net lending when preparing a campaign, feel free to reach out to us. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing#morpho-multi-market-campaign) 🦋 Morpho multi-market campaign ---------------------------------------------------------------------------------------------------------------------------------------------- With Merkl you can **incentivize a single token (e.g. USDC) across all Morpho markets with just one campaign!** No need to precise a specific markets or vault to incentivize. Merkl detects all Morpho markets where the selected incentivized token is active and also identifies every wallet that interacted with those markets. Then, Merkl automatically cascades rewards across every whitelisted Morpho markets where the token is used based on: * the liquidity and size of each market * the user’s share of liquidity To create a multi-market campaign, you just need to select any of these three options when selection an action to incentivize in the Choose target step in Merkl Studio: * `Supply a token to any market` * `Borrow a token from any market` * `Use a token as collateral on any market`  **Who is this designed for?** The multi-market campaign feature is especially aimed at **token issuers**, such as stablecoin protocols. It allow them to grow their token easily by running a campaign across all Morpho markets — for example, rewarding DeFi users who use their token as collateral. [PreviousToken Holding Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms) [NextEncompassing Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing) Last updated 1 month ago * [🫴🏼 Supported protocols](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing#supported-protocols) * [🔁 Preventing lending loops](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing#preventing-lending-loops) * [🦋 Morpho multi-market campaign](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing#morpho-multi-market-campaign) --- # Concentrated Liquidity Campaigns | Merkl Docs [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#overview) 🌐 Overview ---------------------------------------------------------------------------------------------------------------------- Merkl’s Concentrated Liquidity campaigns allow campaign creators to reward Liquidity Providers (LPs) on concentrated liquidity AMMs like Uniswap V4, Uniswap v3, Quickswap, and Sushiswap. Unlike traditional incentives where users are rewarded based on deposit amount, Concentrated Liquidity campaigns reward LPs based on **how they provide liquidity** — within specific price ranges — **and their contribution to the overall liquidity of the pool.** LPs who provide liquidity in optimal, high-impact ranges are rewarded more generously, ensuring capital efficiency.  [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#reward-formula) 🔢 Reward formula ---------------------------------------------------------------------------------------------------------------------------------- When campaign creators launch concentrated liquidity campaigns, they define: * The pool to be incentivized (using the **pool address or ID**) * A **reward period** * A set of **incentive parameters**, which define how rewards will be distributed among liquidity providers. * **In-Range positions only**: Only reward positions that are being used in swaps * **Liquidity Contribution**: Measures the **time-weighted contribution of a position to the overall liquidity in the pool**. Positions that remain tightly concentrated around the active tick contribute more liquidity—assuming equal TVL—than those spread across a wider range. * **Token 0 holding**: The share of token 0 held by a position relative to the total token 0 in the pool. * **Token 1 holding**: The share of token 1 held by a position relative to the total token 1 in the pool. A position is "in range" when the current market price falls within the price range specified by the position's lower and upper ticks. When a position is in range, it actively provides liquidity for trades and earns fees. Out-of-range positions do not contribute to liquidity at the current price and therefore don't earn trading fees. We highly recommend only rewarding in range positions. A position might generate high fees during a short burst of activity, but if it wasn’t consistently concentrated throughout the reward period, it won’t earn significant rewards. What matters here is **sustained concentration over time**, not short-term volume or swap activity. Each factor is assigned a weight (% liquidity contribution, % token0, % token1), which the campaign creator defines when setting up the campaign in Merkl Studio. Merkl analyzes liquidity within the pool during the incentive period and assigns rewards based on these 3 parameters. With this setup, this is as if the overall incentive budget was split in 3, with a proportion being shared by LPs based on how much liquidity they have on the active tick, a proportion shared based on the overall amount of token 0 they've held and a last portion based on the relative token 1 balance they've had in their position during the time period. Merkl released an improved version of its concentrated liquidity reward engine to bring major enhancements—delivering a more performant, stable, and JIT attack-resistant reward mechanism. The system enables precise measurement of liquidity over time, resulting in more deterministic and reliable attribution of LP contributions while minimizing the influence of short-term volatility. ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#example-calculation) 🧮 Example Calculation If incentive weights are set as: * Liquidity contribution = 50% * Token 0 = 25% * Token 1 = 25% Then: * A user representing 40% of the total liquidity in the pool (and hereby earning ~40% of the fees accruing to the pool) receives 20% of total rewards (40% × 50%). * A user holding 30% of Token 0 receives 7.5% of total rewards (30% × 25%). * A user holding 20% of Token 1 receives 5% of total rewards (20% × 25%). [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#reward-strategy-examples) ♟️ Reward strategy examples ------------------------------------------------------------------------------------------------------------------------------------------------------ Campaign creators can fine-tune parameters to match their objectives: * **Encouraging deep liquidity:** Increasing the weight of liquidity contribution / fee earned to encourage deep liquidity in high-volume trading ranges. * **Stablecoin peg protection:** To help maintain a stablecoin peg (e.g., USDC), increasing the weight of Token 0 rewards can encourage LPs to hold more of the pegged token in the pool, discouraging dumps and supporting stability. * **Optimized tight range incentives:** With Uniswap V4 Hooks, LPs can implement automated rebalancing strategies to maintain optimal tight-range positions and maximize reward efficiency. Here are some suggestions depending on your needs and pool type: * For stable pools/pegged pools (e.g., USDC/USDT or WBTC/BTC): Liquidity contribution = 80%, token0 = 10%, token1 = 10% * For volatile pools (e.g., WETH/USDC): Liquidity contribution = 20%, token0 = 40%, token1 = 40% (the higher the volatility, the higher the weights for token0 and token1 percentages should be) * You can also refer to the Merkl blog about [liquidity walls](https://blog.merkl.xyz/merkl-insights-how-can-incentives-prevent-your-token-from-dumping) explaining how to prevent a token from dumping, or a stablecoin from losing its peg Merkl is not responsible for defining your strategy and targets. Nevertheless, you can refer to live campaigns to look for typical APRs and/or parameter weights on similar campaigns. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#sampling-and-anti-dos) 💉 Sampling and Anti-DoS ------------------------------------------------------------------------------------------------------------------------------------------------ For large, high-activity pools in Uniswap v3 and similar AMMs, Merkl samples the largest swaps rather than processing every transaction. * Out-of-range positions detected during sampled swaps are excluded from rewards. * Users earning less than 0.0000001% of total rewards are filtered out. * Positions with less than $10 liquidity are disqualified. To maximize rewards, LPs should actively manage their positions to stay in-range. On the other hand, Uniswap V4 incentive distribution leverages Merkl's `LogProcessor` algorithm, which continuously tracks **the state of each pool in real time.** As a result, each campaign calculates an average value for each position, ensuring users are rewarded based on both the size of their position and how long they keep it open. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#out-of-range-liquidity) ⛔ Out of range liquidity ------------------------------------------------------------------------------------------------------------------------------------------------- Campaign creators can choose whether to reward out-of-range liquidity. By default, only in-range positions receive rewards. We strongly recommend incentivizing in-range liquidity, as this ensures active liquidity provision and avoids rewarding idle capital. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#fake-volume-attacks-detection) 🔎 Fake volume attacks detection ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Merkl automatically detects and blacklists users attempting to game the system via: * Wash trading: Creating tight positions and self-trading to earn rewards. * Frequent rebalancing: If mistaken for wash trading, may trigger blacklisting. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#tick-price-limits-and-eligibility-on-uniswap-v4) ☑️ Tick price limits & eligibility on Uniswap v4 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- To qualify for rewards under a campaign with a tick price limits eligibility rule, a liquidity position must meet both of the following conditions: * (if set by the campaign creator) Upper Tick Price must be below the specified `threshold_0`: Upper Tick Price < `threshold_0` * (Resp.) Lower Tick Price must be above the specified threshold: Lower Tick Price > `threshold_1` Here, price refers to the ratio of token 1 to token 0. For example, if token 1 is ETH and token 0 is BTC, the price reflects the ETH/BTC exchange rate. This rule ensures that only positions providing liquidity within a targeted price range are eligible for rewards. Positions exceeding these limits on either side are not eligible. Example: Suppose the thresholds are: * Upper Price Threshold = 1,050 token 1 per token 0 * Lower Price Threshold = 950 token 1 per token 0 Then: * A position from 960 to 1,040 qualifies (upper < 1,050, lower > 950). * A position from 940 to 1,020 does not qualify (lower < 950). * A position from 990 to 1,080 does not qualify (upper > 1,050). This setup encourages liquidity within a narrow, strategic price corridor, optimizing depth and efficiency around critical price levels. The thresholds are set independently — it is possible to define a limit for the upper tick price without setting one for the lower tick price (and vice versa). [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#aprs-calculation) 📈 APRs calculation -------------------------------------------------------------------------------------------------------------------------------------- APRs shown on the Merkl interface for concentrated liquidity campaigns represent average values. They are calculated by dividing the annualized reward emissions for a pool by its current TVL. However, actual APR varies per position. A position may earn more or less than the displayed average depending on factors like: * How tightly liquidity is concentrated * How others are providing liquidity * The weight of campaign’s parameters Example: * If liquidity contribution = 99%, a full-range position may earn minimal rewards despite providing high liquidity. * If Token A = 60% and Token B = 10%, LPs holding more Token A will earn disproportionately higher rewards and you may be better off skewing your position so it has more of token A than of token B. The TVL of concentrated liquidity pools is updated every 2 hours and excludes blacklisted liquidity (so if the pool TVL is $1M and a blacklisted user holds 30% of the pool's TVL, the displayed TVL will be $700k) [PreviousCampaign Types](https://docs.merkl.xyz/merkl-mechanisms/campaign-types) [NextAirdrop Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop) Last updated 1 month ago * [🌐 Overview](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#overview) * [🔢 Reward formula](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#reward-formula) * [🧮 Example Calculation](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#example-calculation) * [♟️ Reward strategy examples](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#reward-strategy-examples) * [💉 Sampling and Anti-DoS](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#sampling-and-anti-dos) * [⛔ Out of range liquidity](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#out-of-range-liquidity) * [🔎 Fake volume attacks detection](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#fake-volume-attacks-detection) * [☑️ Tick price limits & eligibility on Uniswap v4](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#tick-price-limits-and-eligibility-on-uniswap-v4) * [📈 APRs calculation](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms#aprs-calculation) --- # Incentive Mechanisms | Merkl Docs Merkl is designed to be highly versatile, supporting a wide range of incentive structures across both DeFi and broader Web3 ecosystems. [](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#campaign-design) 🔧 Campaign Design -------------------------------------------------------------------------------------------------------- When creating a campaign on Merkl, campaign creators can configure: ### [](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#id-1-campaign-type) 1️⃣ Campaign Type [Campaign types](https://docs.merkl.xyz/merkl-mechanisms/campaign-types) define the action that needs to be done to be eligible to rewards. Merkl supports multiple campaign types, rewarding users for both financial activities (e.g., liquidity provision, lending) and other onchain/offchain actions. Some of the most commonly used campaign types include * [**Concentrated Liquidity**](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms) : Rewards liquidity providers (LPs) in Concentrated Liquidity AMMs (CLAMMs) such as Uniswap V3 or Uniswap V4. * [**Lending & Borrowing**](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing) : Encourages activity on lending protocols like Morpho, Euler, or Aave, or rewards specific behaviors within these protocols. * [**Airdrop**](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop) : Distributes tokens to a potentially millions of users based on either a JSON file or a snapshotted token balance. * [**Token Holding**](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms) : Rewards users for holding an ERC20 token over time. This can be used for virtually any protocol that gives ERC20 receipt tokens to their stakeholders. ### [](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#id-2-distribution-type) 2️⃣ Distribution Type [Distribution types](https://docs.merkl.xyz/merkl-mechanisms/distributions) define the **reward distribution model** and **how the total campaign budget is spent over time**. Common models include: * [Variable reward rate campaigns](https://docs.merkl.xyz/merkl-mechanisms/distributions#variable-reward-rate-campaigns) : rewards are distributed proportionally based on time-weighted liquidity within the eligibility pool. * [Fixed reward rate campaigns](https://docs.merkl.xyz/merkl-mechanisms/distributions#fixed-reward-rate-campaigns) : a predefined amount of rewards per unit of liquidity is distributed at a fixed rate. * [Capped reward rate campaigns](https://docs.merkl.xyz/merkl-mechanisms/distributions#capped-reward-rate-campaigns) : similar to variable rate campaigns, but with a maximum APR that cannot be exceeded. ### [](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#id-3-scoring-type) 3️⃣ Scoring Type [Scoring types](https://docs.merkl.xyz/merkl-mechanisms/scoring) define **how individual user contributions are measured and converted into reward shares**. Common models include: * **1:1 mapping (default)**: User reward share equals their share of total contributions * **Max balance scoring**: Caps eligible balances by taking the minimum between a user's time-weighted balance and a predefined maximum ### [](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#id-4-customization-options) 4️⃣ Customization Options Merkl supports a wide range of [customization options](https://docs.merkl.xyz/merkl-mechanisms/customization-options) to further personalize campaigns beyond core settings. These include filters to dynamically restrict or boost the eligible users for a campaign based on whether they hold a token. [](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#feature-compatibility) 🔄 Feature Compatibility -------------------------------------------------------------------------------------------------------------------- Not all campaign types are compatible with all distribution types. Similarly, some customization options may only work with specific campaign or distribution types. To check the status of Merkl’s features, the compatibility between campaign types, distribution or scoring types, or to view the list of supported chains and tokens, simply visit [**Merkl Studio**](https://studio.merkl.xyz/) and simulate the creation of a campaign. Some [customization options](https://docs.merkl.xyz/merkl-mechanisms/customization-options) , [campaign types](https://docs.merkl.xyz/merkl-mechanisms/campaign-types) , [distribution types](https://docs.merkl.xyz/merkl-mechanisms/distributions) and [scoring types](https://docs.merkl.xyz/merkl-mechanisms/scoring) are not configurable directly via Merkl Studio. In such cases, we recommend reaching out to us — we can either configure your campaign for you or provide dedicated API endpoints to help you set it up. Merkl’s capabilities continuously expand, adding support for new campaign types, distribution methods, and customization options. If you need a custom incentivization model, contact us by opening a [BD ticket on Discord](https://discord.gg/jnYfrGxDbe) or sending a message on Telegram. [PreviousTechnical Overview](https://docs.merkl.xyz/merkl-mechanisms/technical-overview) [NextCampaign Types](https://docs.merkl.xyz/merkl-mechanisms/campaign-types) Last updated 1 month ago * [🔧 Campaign Design](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#campaign-design) * [1️⃣ Campaign Type](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#id-1-campaign-type) * [2️⃣ Distribution Type](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#id-2-distribution-type) * [3️⃣ Scoring Type](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#id-3-scoring-type) * [4️⃣ Customization Options](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#id-4-customization-options) * [🔄 Feature Compatibility](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms#feature-compatibility) --- # Airdrop Campaigns | Merkl Docs Merkl supports airdrop campaigns, simplifying the process for protocols looking to airdrop tokens to their community by allowing them to get it done in a few minutes with just a few clicks while minimizing gas fees. Merkl supports two different types of airdrops: 1. **Custom Allocation Airdrops**: Campaign creators define the reward distribution, specifying which users receive what amount. Providers upload a JSON file with allocation details, and Merkl handles the distribution via its claim system. 2. **Snapshot-Based Airdrops**: Merkl distributes rewards based on a snapshot of a given token’s balance at a chosen point in time. Airdrops do not appear “live” like continuously computed campaigns because the Merkl Engine performs no ongoing calculation. To review your airdrop in the main opportunities page after creation, use this filtered view: [https://app.merkl.xyz/?status=LIVE%2CSOON%2CPAST&sort=lastCampaignCreatedAt-desc](https://app.merkl.xyz/?status=LIVE%2CSOON%2CPAST&sort=lastCampaignCreatedAt-desc) \\ [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop#json-airdrops) JSON airdrops --------------------------------------------------------------------------------------------------- For Custom Allocation Airdrops, providers only need to upload a JSON file specifying user addresses and reward amounts. To create your JSON Airdrop campaign on Merkl, visit this [page](https://studio.merkl.xyz/create-campaign/airdrop) . The expected format for the JSON is the following Copy type AirdropJSON = { // Token being distributed rewardToken: string; // User rewards rewards: { // recipient: user address [recipient: string]: { // Reason: how the user got the rewards [reason: string]: string; // value: amount with all decimals as a string }; }; }; Example: * **rewardToken:** The token being distributed. * **rewards:** User rewards with recipient addresses and reasons for the rewards. **Important**: All addresses in your JSON file MUST be in [checksummed format](https://eips.ethereum.org/EIPS/eip-55) . Non-checksummed addresses will cause the campaign to fail. Use tools like [Etherscan](https://etherscan.io/) or ethers.js `getAddress()` to convert addresses to the correct format. ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop#fees-for-airdrops) Fees for airdrops Merkl applies a 0.5% fee to airdrop campaigns. This fee is added on top of the total airdropped amount, ensuring recipients receive the full intended distribution. * If you want exactly 100,000 tokens to be distributed to users, you need to provide 100,502.51 tokens (calculated as 100,000 / (1 - 0.5%)). * If you prefer to send exactly 100,000 tokens from your wallet, then the total sum of allocations in your JSON file should be 99,500 tokens (calculated as 100,000 \* (1 - 0.5%)). Our frontend automatically calculates the correct amount for you. ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop#airdrop-timing) Airdrop timing Once an airdrop campaign is created and launched on Merkl, it usually takes up to **12 hours** before the **tokens become claimable** by users (as the airdrop becomes available at the next [reward update](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-updates) on the target chain). We recommend until the rewards are claimable **to notify your community** that the airdrop is live. As mentioned above, airdrops always appear as `PAST` on the Merkl app, with **campaign end date** in the past. Note that the end date on the Merkl app is **different from the airdrop claim end date**: it is the date when new rewards stop distributing. Even after a campaign is marked as “ended” on the Merkl App, users can still claim their tokens via their Merkl dashboard. The **campaign end date** on the Merkl App **cannot be modified**. ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop#controlling-claim-dates-with-token-wrappers) Controlling Claim Dates with Token Wrappers As explained [in this page of our docs](https://docs.merkl.xyz/merkl-mechanisms/features#-infinite-customizability-with-token-wrappers) , it is possible to distribute wrappers of standard ERC20 tokens using Merkl. In the context of an airdrop, we offer a wrapper type that allows you to retain the tokens you airdrop in your wallet and maintain full control over when they become claimable by users. Once your wrapper is deployed and you've minted wrapper tokens, the process works as follows: 1. Create your airdrop campaign on Merkl, distributing your wrapper token instead of the underlying token you want to airdrop 2. Wait for a reward update for the wrapper tokens to become claimable on Merkl 3. The wrapper tokens are typically marked as test tokens, making them invisible on the frontend 4. Users can only claim the actual tokens once you: * Approve the wrapper token contract to spend the underlying token * Hold the underlying tokens in your address This approach is particularly useful for TGE (Token Generation Event) processes where tokens must only become claimable after a specific date chosen by the campaign creator. From a user perspective, users only see the underlying token arriving in their wallet, not the wrapper token. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop#token-balance-airdrops) Token balance airdrops --------------------------------------------------------------------------------------------------------------------- Merkl allows you to distribute tokens to holders based on their snapshotted balance at a chosen moment in time. For this type of campaign, in addition to the reward amount, campaign creators must specify: * Snapshot Date – The balance snapshot is taken at the last block before this date. * Distribution Date – The date on which rewards should be distributed. * Snapshot Name – A label for your snapshot. [PreviousConcentrated Liquidity Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/concentrated-liquidity-mechanisms) [NextToken Holding Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms) Last updated 18 days ago * [JSON airdrops](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop#json-airdrops) * [Fees for airdrops](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop#fees-for-airdrops) * [Airdrop timing](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop#airdrop-timing) * [Controlling Claim Dates with Token Wrappers](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop#controlling-claim-dates-with-token-wrappers) * [Token balance airdrops](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop#token-balance-airdrops) Copy { "rewardToken": "0x1a7e4e63778B4f12a199C062f3eFdD288afCBce8", "rewards": { "0x529619a10129396a2F642cae32099C1eA7FA2834": { "reason1": "1827034243855622331" }, "0x0C2553e4B9dFA9f83b1A6D3EAB96c4bAaB42d430": { "reason1": "1827034243855622331", "reason2": "1035298980258165611" } } } --- # Encompassing Campaigns | Merkl Docs Merkl's All Encompassing Campaigns enable protocols to distribute rewards without requiring Merkl's Engine to calculate reward allocation. In this model, partners provide some API endpoints containing opportunity data and rewards, which are distributed based on the provided output. The Merkl Engine aggregates the computed reward data provided by the partner into a Merkle root and pushes it onchain, enabling users to claim their rewards. Once [a reward update](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-updates) has been processed, it becomes immutable and cannot be reverted. Nevertheless, campaign data can be dynamically updated throughout the campaign duration by modifying the reward endpoint output, with the final update required before the campaign's end date. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#campaign-configuration) 🛠️ Campaign configuration ------------------------------------------------------------------------------------------------------------------------------ Campaigns creators must provide the following information upon creation: * 📅 Start Date – The date on which the campaign starts. * 📅 End Date – The date on which the campaign ends. * 🎁 Reward url - A public endpoint returning a reward JSON file. * 📊 Data url - A public endpoint returning a data JSON file. ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#id-1.-reward-json) 1\. 🎁 Reward JSON The expected format for the JSON reward is the following Copy type EncompassingJSON = { // Token being distributed rewardToken: string; // User rewards rewards: { // recipient: user address [recipient: string]: { // Reason: how the user got the rewards [reason: string]: { // amount: amount with all decimals as a string amount: string; // timestamp: unix timestamp in seconds, date at which the reward is sent to the recipient (must not exceed the end date of the campaign) timestamp: string; } }; }; }; Example: * **rewardToken:** The token being distributed. * **rewards:** User rewards with recipient addresses, reasons, amount and timestamp for the rewards. Good to know: * `timestamp` is the unix timestamp in seconds, date at which the reward is sent to the recipient. This timestamp must not exceed the end date of the campaign (it will not be processed if it's after the end date), and if it's before the start date of the campaign, the reward will be sent to the recipient at the start date. * Once the engine has processed some rewards, even if the reward endpoint is updated, the rewards already distributed can't be reverted. If a campaign creator needs to send additional rewards to the same user, he can do it by adding another reason for the same recipient. Example: **Keep recent history:** Include at least 3/4 days of past entries in your Reward JSON so that, if there are delays, the Merkl engine can still fetch and process recent rewards without requiring you to re-upload old data. **Give yourself a buffer with the end date:** We recommend setting the end date of your campaign 24 hours after you expect to distribute the last funds to make sure all rewards are processed before the end of the campaign. ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#id-2.-data-json) 2\. 📊 Data JSON The expected format for the JSON data is the following Example: This data will be used to display the campaign in the Merkl frontend. ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#validating-your-endpoints) Validating your endpoints You can use this python script to validate that your endpoints are in the correct format[](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#you-can-use-this-python-script-to-validate-that-your-endpoints-are-in-the-correct-format) ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#important-note) ⚠️ Important Note Merkl applies a 0.5% fee to this type of campaigns. This fee is added on top of the total airdropped amount, ensuring recipients receive the full intended distribution. * 💡 If you want exactly 100,000 tokens to be distributed to users, you need to provide 100,502.51 tokens (calculated as 100,000 / (1 - 0.5%)). * 💡 If you prefer to send exactly 100,000 tokens from your wallet, then the total sum of allocations in your JSON file should be 99,500 tokens (calculated as 100,000 \* (1 - 0.5%)). Our frontend automatically calculates the correct amount for you. ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#distribution-lag) ⏳ Distribution lag Tokens become claimable at the next [reward update](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-updates) on the target chain, which typically occurs within 8 hours. If you plan to announce the distribution, we recommend waiting until the rewards are claimable to notify your users. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#tutorial-for-static-encompassing-campaigns) Tutorial for static encompassing campaigns ------------------------------------------------------------------------------------------------------------------------------------------------------------------ If you are running a quest on your app where users become eligible to rewards after a while, it can be beneficial to create an encompassing campaign because your quest will be exposed to our user base. However, you probably don't need to go through the trouble of developing a real API endpoint for us because the data is almost static (only updated once, at the end of the quest). What we recommend is doing this via gists. ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#data-json) Data JSON Here is an example data JSON using a gist: [https://gist.githubusercontent.com/BaptistG/576bd5711fded3f44d906efbcaff80e0/raw](https://gist.githubusercontent.com/BaptistG/576bd5711fded3f44d906efbcaff80e0/raw) **Important**: You need to give us a **raw** URL of a **public** gist. **Creating a public gist:** Go to [https://gist.github.com/](https://gist.github.com/) , fill in the data and select `Create public gist` **Getting the raw URL:** Once you create your gist, the URL of the page you are on should look something like this: `https://gist.github.com/BaptistG/576bd5711fded3f44d906efbcaff80e0`. To get the raw url, you need to add `/raw` at the end (`https://gist.github.com/BaptistG/576bd5711fded3f44d906efbcaff80e0/raw` with the previous example). ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#reward-json) Reward JSON You must first initialize the gist of the reward URL. You do this by creating a public gist of the following format: Here is an example if you want to airdrop [WETH](https://etherscan.io/token/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2) on Ethereum: [https://gist.github.com/BaptistG/e9bc9e9703a40cd6ad7e30d3e4e039a3/42921f90a660bfb7db8b6f890adc725644ad1490](https://gist.github.com/BaptistG/e9bc9e9703a40cd6ad7e30d3e4e039a3/42921f90a660bfb7db8b6f890adc725644ad1490) You can now use the raw URL to initialize the campaign: `https://gist.githubusercontent.com/BaptistG/e9bc9e9703a40cd6ad7e30d3e4e039a3/raw/` (you will notice that this URL has data in there, this is because it is the latest version of the file) ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#create-the-campaign) Create the campaign You now have everything you need to create the campaign. You will need to choose the start and end dates of the campaign and commit the airdropped amount upfront. If you don't airdrop all the tokens by the end of the campaign, you will automatically get the undistributed tokens back #### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#generating-the-payload) Generating the payload The Merkl Studio does not yet support creating encompassing campaigns. We recommend calling the [encode batch](https://api.merkl.xyz/docs#tag/config/post/v4configencodebatch) route on the API to generate a Gnosis Safe payload for your campaign. The Gnosis Safe payload will be under the key `safePayload` ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#airdropping-the-rewards) Airdropping the rewards Before the end of the campaign you created, you need to update the rewards endpoint to tell Merkl to airdrop the rewards. To do so you should go to your gist, click edit and add data. For example, if I want to airdrop the following rewards of my token that has 18 decimals to 3 users where: * User 1 gets 1 token * User 2 gets 4 tokens * User 3 gets 6 tokens The gist should look like this: Here is an example for the WETH airdrop: [https://gist.github.com/BaptistG/e9bc9e9703a40cd6ad7e30d3e4e039a3](https://gist.github.com/BaptistG/e9bc9e9703a40cd6ad7e30d3e4e039a3) **Important:** * Your GitHub account has the power to update the gist, so if you get your account compromised, someone could airdrop themselves everything. * You must update this gist at least 12 hours before the scheduled end of the campaign. If you don't, our engine might not distribute the rewards and send you all the tokens back at the end of the campaign instead of running the airdrop * Don't forget that Merkl will take a small fee on the tokens you send, you can't distribute more than what is in our distributor, to verify the amount, go to the campaign page on our app. [PreviousLending and Borrowing Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing) [NextStaking & Restaking Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/staking) Last updated 18 days ago * [🛠️ Campaign configuration](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#campaign-configuration) * [1\. 🎁 Reward JSON](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#id-1.-reward-json) * [2\. 📊 Data JSON](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#id-2.-data-json) * [Validating your endpoints](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#validating-your-endpoints) * [⚠️ Important Note](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#important-note) * [⏳ Distribution lag](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#distribution-lag) * [Tutorial for static encompassing campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#tutorial-for-static-encompassing-campaigns) * [Data JSON](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#data-json) * [Reward JSON](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#reward-json) * [Create the campaign](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#create-the-campaign) * [Airdropping the rewards](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing#airdropping-the-rewards) Copy { "rewardToken": "0xE0688A2FE90d0f93F17f273235031062a210d691", "rewards": { "0x9f76a95AA7535bb0893cf88A146396e00ed21A12": { "epoch-1": { "amount": "40000000000000000000", "timestamp": "1732294694" } }, "0xfdA462548Ce04282f4B6D6619823a7C64Fdc0185": { "epoch-2": { "amount": "100000000000000000000", "timestamp": "1741370722" } } } } Copy { "rewardToken": "0xE0688A2FE90d0f93F17f273235031062a210d691", "rewards": { "0x9f76a95AA7535bb0893cf88A146396e00ed21A12": { "epoch-1": { "amount": "40000000000000000000", "timestamp": "1732294694" // at this timestamp, `40000000000000000000` tokens will be claimable by the recipient }, "epoch-2": { // new reason for the same recipient "amount": "100000000000000000000", "timestamp": "1741370722" // at this timestamp, `100000000000000000000` additional tokens will be claimable by the recipient } }, "0xfdA462548Ce04282f4B6D6619823a7C64Fdc0185": { "epoch-2": { "amount": "100000000000000000000", "timestamp": "1741370722" } } } } Copy type DataJSON = { tvl: string; apr: string; // in decimal opportunityName: string; // optional } Copy { "tvl": "100000", "apr": "0.5", // 0.5 in decimal = 50% APR "opportunityName": "Testing distribution aglaMerkl" } Copy import requests import json import re from typing import Dict, Any, Optional def is_number_regex(s): # Matches integers and decimals (including negative) return bool(re.match(r'^-?\d+(\.\d+)?$', s)) def validate_data_url(url: str) -> Optional[Dict[str, Any]]: """ Validate that the data URL returns the expected format: { "tvl": "100000", "apr": "0.5", "opportunityName": "Testing distribution aglaMerkl" } """ print(f"\n=== Validating Data URL ===") print(f"URL: {url}") try: response = requests.get(url) response.raise_for_status() data = response.json() # Check required fields required_fields = ["tvl", "apr", "opportunityName"] missing_fields = [field for field in required_fields if field not in data] if missing_fields: print(f"❌ INVALID: Missing required fields: {missing_fields}") return None # Validate types if not isinstance(data["tvl"], str): print(f"❌ INVALID: 'tvl' should be a string, got {type(data['tvl']).__name__}") return None if not isinstance(data["apr"], str): print(f"❌ INVALID: 'apr' should be a string, got {type(data['apr']).__name__}") return None if not isinstance(data["opportunityName"], str): print(f"❌ INVALID: 'opportunityName' should be a string, got {type(data['opportunityName']).__name__}") return None # Validate numeric formats if not is_number_regex(data["tvl"]): print(f"❌ INVALID: 'tvl' should be a numeric string, got '{data['tvl']}'") return None if not is_number_regex(data["apr"]): print(f"❌ INVALID: 'apr' should be a numeric string, got '{data['apr']}'") return None print("✅ VALID: Data URL format is correct") print(f" TVL: {data['tvl']}") print(f" APR: {data['apr']}") print(f" Opportunity Name: {data['opportunityName']}") return data except requests.RequestException as e: print(f"❌ ERROR: Failed to fetch data from URL: {e}") return None except json.JSONDecodeError as e: print(f"❌ ERROR: Invalid JSON response: {e}") return None def validate_reward_url(url: str) -> Optional[Dict[str, Any]]: """ Validate that the reward URL returns the expected format: { "rewardToken": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "rewards": { "0x37305B1cD40574E4C5Ce33f8e8306Be057fD7341": { "season1": { "amount": "1000000000000000000", "timestamp": "1741370722" } } } } """ print(f"\n=== Validating Reward URL ===") print(f"URL: {url}") try: response = requests.get(url) response.raise_for_status() data = response.json() # Check required top-level fields if "rewardToken" not in data: print(f"❌ INVALID: Missing 'rewardToken' field") return None if "rewards" not in data: print(f"❌ INVALID: Missing 'rewards' field") return None if not isinstance(data["rewardToken"], str): print(f"❌ INVALID: 'rewardToken' should be a string, got {type(data['rewardToken']).__name__}") return None if not isinstance(data["rewards"], dict): print(f"❌ INVALID: 'rewards' should be a dict, got {type(data['rewards']).__name__}") return None # Validate rewards structure for address, seasons in data["rewards"].items(): if not isinstance(seasons, dict): print(f"❌ INVALID: Rewards for {address} should be a dict, got {type(seasons).__name__}") return None for season_name, season_data in seasons.items(): if not isinstance(season_data, dict): print(f"❌ INVALID: Season data for {address}/{season_name} should be a dict") return None if "amount" not in season_data: print(f"❌ INVALID: Missing 'amount' in {address}/{season_name}") return None if "timestamp" not in season_data: print(f"❌ INVALID: Missing 'timestamp' in {address}/{season_name}") return None if not isinstance(season_data["amount"], str): print(f"❌ INVALID: 'amount' should be a string in {address}/{season_name}") return None if not isinstance(season_data["timestamp"], str): print(f"❌ INVALID: 'timestamp' should be a string in {address}/{season_name}") return None print("✅ VALID: Reward URL format is correct") print(f" Reward Token: {data['rewardToken']}") print(f" Total Addresses: {len(data['rewards'])}") return data except requests.RequestException as e: print(f"❌ ERROR: Failed to fetch data from URL: {e}") return None except json.JSONDecodeError as e: print(f"❌ ERROR: Invalid JSON response: {e}") return None def calculate_user_rewards(reward_data: Dict[str, Any], decimals: int = 18): """ Calculate and print the amount each user would receive (divided by 1e18) """ print(f"\n=== User Reward Amounts ===") if not reward_data or "rewards" not in reward_data: print("No reward data available") return total_amount = 0 user_totals = {} for address, seasons in reward_data["rewards"].items(): user_total = 0 for reason, season_data in seasons.items(): amount_wei = int(season_data["amount"]) amount_tokens = amount_wei / (10 ** decimals) user_total += amount_tokens user_totals[address] = user_total total_amount += user_total # Print sorted by amount (descending) sorted_users = sorted(user_totals.items(), key=lambda x: x[1], reverse=True) for address, amount in sorted_users: print(f"{address}: {amount:,.6f} tokens") print(f"\n{'='*60}") print(f"Total Amount Distributed: {total_amount:,.6f} tokens") print(f"{'='*60}") return total_amount def check_campaign_rewards(campaign_id: str, expected_total: float, decimals: int = 18): """ Check if the campaign has enough budget for the expected total rewards """ print(f"\n=== Checking Campaign Rewards ===") url = f"https://api.merkl.xyz/v4/campaigns/{campaign_id}" try: response = requests.get(url) response.raise_for_status() data = response.json() total_budget_wei = int(data.get("amount", "0")) total_budget_tokens = total_budget_wei / (10 ** decimals) print(f"Campaign ID: {campaign_id}") print(f"Total Budget: {total_budget_tokens:,.6f} tokens") print(f"Expected Total Rewards: {expected_total:,.6f} tokens") if total_budget_tokens >= expected_total: print("✅ The campaign has enough budget for the expected rewards.") else: print("❌ The campaign does NOT have enough budget for the expected rewards.") except requests.RequestException as e: print(f"❌ ERROR: Failed to fetch campaign metrics: {e}") except json.JSONDecodeError as e: print(f"❌ ERROR: Invalid JSON response: {e}") if __name__ == "__main__": # Example URLs - replace with actual URLs data_url = "https://gist.githubusercontent.com/BaptistG/576bd5711fded3f44d906efbcaff80e0/raw" reward_url = "https://gist.github.com/BaptistG/e9bc9e9703a40cd6ad7e30d3e4e039a3/raw" decimals = 18 # Adjust if reward token has different decimals campaign_id = "3141666711044140572" # Leave empty if campaign not created yet. If filled with the campaign DB ID, the script will check if the amounts match and if you have enough budget in the campaign. print("=" * 60) print("URL Format Validation Script") print("=" * 60) # Validate data URL data_result = validate_data_url(data_url) # Validate reward URL reward_result = validate_reward_url(reward_url) # If reward URL is valid, calculate user amounts if reward_result: total_amount = calculate_user_rewards(reward_result, decimals) # If campaign ID is provided, check campaign rewards if campaign_id and total_amount is not None and campaign_id.strip() != "": check_campaign_rewards(campaign_id, total_amount, decimals) print("\n" + "=" * 60) print("Validation Complete") print("=" * 60) Copy { "rewardToken": "
", "rewards": {} } Copy [\ {\ "distributionChainId": 1, \ "amount": "1000000000000000000",\ "computeChainId": 1,\ "creator": "0x0000000000000000000000000000000000000000",\ "startTimestamp": 1763985600,\ "rewardToken": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",\ "campaignType": 27,\ "endTimestamp": 1766613600,\ "dataUrl": "https://gist.github.com/BaptistG/576bd5711fded3f44d906efbcaff80e0/raw",\ "rewardsUrl": "https://gist.githubusercontent.com/BaptistG/e9bc9e9703a40cd6ad7e30d3e4e039a3/raw",\ "hooks": []\ }\ ] Copy { "rewardToken": "", "rewards": { "": { "season1": { "amount": "1000000000000000000", "timestamp": "1741370722" } }, "": { "season1": { "amount": "4000000000000000000", "timestamp": "1741370722" } }, "": { "season1": { "amount": "6000000000000000000", "timestamp": "1741370722" } } } } --- # Scoring Types | Merkl Docs [](https://docs.merkl.xyz/merkl-mechanisms/scoring#what-is-scoring) What is Scoring? ----------------------------------------------------------------------------------------- **Scoring types** define how individual user contributions are measured and converted into reward shares. While [distribution types](https://docs.merkl.xyz/merkl-mechanisms/distributions) determine the overall reward model and budget allocation, scoring types control how each user's activity is scored within that model. At its core, Merkl computes **time-weighted integrals** of user balances or contributions—essentially tracking how much liquidity or assets each user provided over time. [](https://docs.merkl.xyz/merkl-mechanisms/scoring#scoring-types-overview) Scoring Types Overview ------------------------------------------------------------------------------------------------------ Merkl supports various scoring methods, allowing campaign creators to choose how individual user contributions are measured. Each scoring type applies a different function to the time-weighted integrals, creating distinct reward allocation patterns. * **Default scoring (1:1 mapping)**: By default, Merkl uses a proportional scoring system where a user's share of rewards equals their share of the total time-weighted contributions. For example, if a user contributed 10% of the total liquidity-time across all participants, they receive 10% of the rewards (in a variable APR campaign). * **Custom scoring functions**: Campaign creators can apply different scoring functions to transform these integrals before calculating reward shares. Examples include: * **Maximum balance cap**: Taking the minimum between a user's time-weighted balance and a predefined cap—this limits how much eligible balance counts toward rewards, preventing excessive concentration. * **Logarithmic scoring**: Applying a logarithmic function to the time-weighted integral—this reduces the advantage of large contributors, creating a more equitable distribution where smaller participants receive proportionally higher rewards relative to their contribution size. [PreviousDistribution Types](https://docs.merkl.xyz/merkl-mechanisms/distributions) [NextReward Forwarding](https://docs.merkl.xyz/merkl-mechanisms/reward-forwarding) Last updated 1 month ago * [What is Scoring?](https://docs.merkl.xyz/merkl-mechanisms/scoring#what-is-scoring) * [Scoring Types Overview](https://docs.merkl.xyz/merkl-mechanisms/scoring#scoring-types-overview) --- # Staking & Restaking Campaigns | Merkl Docs Merkl enables tracking and rewarding liquidity deposited in staking or restaking contracts—even if these contracts do not issue receipt tokens to LPs. Below are the custom campaign types currently supported. If you need support for a different contract type, please contact us. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/staking#staking-and-restaking) **Staking and Restaking** ----------------------------------------------------------------------------------------------------------------------- * **Symbiotic Vault**: Merkl can track Symbiotic Vaults, specifically monitoring the value of the underlying tokens deposited by users. This enables highly customizable reward campaigns, such as fixed or variable reward rates over time, points systems, or token distributions. * **Masterchef Vault**: Merkl supports tracking and rewarding liquidity in the most common Masterchef implementations. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/staking#locker) **Locker** ----------------------------------------------------------------------------------------- Locking is a core primitive in DeFi. Merkl can reward liquidity in locker contracts, allowing you to incentivize your most loyal users. Campaign creators can define custom reward curves or boosts, for example, based on the number of months a user locks their position. * **Puffer : Carrot Locker** To have your locker, staking, or restaking contract fully integrated and supported by Merkl, please [contact us on the Merkl Discord by opening a BD ticket](https://discord.com/invite/jnYfrGxDbe) to discuss the integration process. [PreviousEncompassing Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing) [NextDistribution Types](https://docs.merkl.xyz/merkl-mechanisms/distributions) Last updated 6 months ago * [Staking and Restaking](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/staking#staking-and-restaking) * [Locker](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/staking#locker) --- # Token Holding Campaigns | Merkl Docs Merkl enables the creation of token holding campaigns (also known as ERC20 campaigns), where **users earn rewards based on their token balance over time**. At their simplest, these campaigns function like traditional `StakingRewards` contracts. However, Merkl's **high customizability** and **advanced forwarding mechanisms** enable token holding campaigns to support far more flexible and complex use cases—going well beyond the limitations of standard staking systems. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms#campaign-design) Campaign Design ---------------------------------------------------------------------------------------------------------------- ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms#distribution-type) Distribution Type In Token Holding Campaigns, users holding an incentivized ERC20 token in their wallet earn rewards based on their balance. How these rewards are allocated depends on the [distribution and scoring types](https://docs.merkl.xyz/merkl-mechanisms/distributions) and the [customization options](https://docs.merkl.xyz/merkl-mechanisms/customization-options) chosen by the campaign creator. For example, in a [variable reward rate campaign](https://docs.merkl.xyz/merkl-mechanisms/distributions#variable-reward-rate-campaigns) , rewards are distributed proportionally to each user's share of the total token supply. If a user holds 1% of the total supply over a given period, they are eligible to receive 1% of the rewards distributed during that time. [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms#applications) Applications ---------------------------------------------------------------------------------------------------------- Token Holding Campaigns are highly versatile, supporting a wide range of DeFi use cases. Any protocol that issues receipt tokens when users interact with it is automatically supported by Merkl. This includes: * **Constant product AMMs**: Uniswap V2, SushiSwap, and similar liquidity pools * **Lending and borrowing protocols**: Platforms that emit receipt and debt tokens (ERC20 tokens) such as Aave—lenders can be rewarded based on their lending amount over time, and borrowers based on their borrowing amount * **Perpetual DEXes**: Perp protocols that issue receipt tokens to depositors in trading vaults Not all lending and borrowing protocols issue ERC20 receipt or debt tokens when users borrow from them. These protocols require a custom integration within Merkl. You can find more information about these specialized campaigns on the dedicated [lending & borrowing page](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing) . Additionally, some lending/borrowing protocols may require more tailored incentives (e.g., incentivizing lenders while blacklisting users who fold their liquidity). In such cases, a dedicated integration is recommended, similar to the custom integration implemented for Aave. ### [](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms#merkl-api-integration) Merkl API Integration The logic for reward computation is independent from the API logic used to compute APRs and TVLs for the associated opportunity. For the protocol it integrates, the Merkl system can automatically recognize whether a given ERC20 token originates from a specific protocol, and then compute the associated TVL and APR if a campaign is running on it. If you are unsure whether the Merkl API will properly recognize your token as coming from your protocol before creating a campaign, please [contact us on the Merkl Discord by opening a BD ticket](https://discord.com/invite/jnYfrGxDbe) to discuss the integration process. [PreviousAirdrop Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/airdrop) [NextLending and Borrowing Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing) Last updated 1 month ago * [Campaign Design](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms#campaign-design) * [Distribution Type](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms#distribution-type) * [Applications](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms#applications) * [Merkl API Integration](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/erc20-mechanisms#merkl-api-integration) --- # Additional Features | Merkl Docs Beyond campaign types, distribution methods, and customization options, Merkl offers several advanced features to enhance campaign flexibility and reward management. [](https://docs.merkl.xyz/merkl-mechanisms/features#blacklisting) ❌ Blacklisting ------------------------------------------------------------------------------------- Blacklisting excludes specific addresses from receiving rewards.  If a [forwarder](https://docs.merkl.xyz/merkl-mechanisms/reward-forwarding) is blacklisted, all associated users are also ineligible. Example of a staking contract blacklist: * A user holds 10 USDA but has staked 6 USDA in a blacklisted staking contract (forwarder). * Only the 4 USDA in the user’s wallet qualifies for rewards. [](https://docs.merkl.xyz/merkl-mechanisms/features#whitelisting) ✅ Whitelisting ------------------------------------------------------------------------------------- Whitelisting restricts rewards to a specific address or set of addresses (e.g., forwarders, or individual users). Example of Uniswap V3 whitelisting: * A campaign incentivizes LPs in a Uniswap V3 pool with three forwarders — here Automated Liquidity Managers. * The campaign creator whitelists only two forwarders and one user address. * Result: * Only liquidity providers using the two approved forwarders or the whitelisted user will receive rewards * Rewards are distributed normally among whitelisted addresses based on liquidity share. **Whitelisting overrides blacklisting. If an address is whitelisted, all other addresses are automatically blacklisted.** If multiple campaigns run on the opportunity (e.g. Uniswap v4 ETH-USDC), some may have whitelists while others do not. This means that, for the same opportunity, the users receiving rewards can differ. Users should check the campaign details on the opportunity page to confirm eligibility requirements. [](https://docs.merkl.xyz/merkl-mechanisms/features#run-multiple-campaigns-on-the-same-opportunity) 🔥 Run Multiple Campaigns on the Same Opportunity ---------------------------------------------------------------------------------------------------------------------------------------------------------- Merkl allows multiple campaigns to be created simultaneously for the same pool or set of actions. **Why is this useful?** * Co-incentives: Different parties can independently add incentives to the same opportunity. * Flexible Stacking: Multiple campaigns can run alongside each other on the same pool or token, supporting different incentive structures. [](https://docs.merkl.xyz/merkl-mechanisms/features#campaigns-of-any-duration) ⏳ Campaigns of Any Duration --------------------------------------------------------------------------------------------------------------- Merkl campaigns can run for any length of time, from as short as one hour to as long as six months (or more). This flexibility allows for: * Short-term boosts (e.g., flash incentives for new launches). * Long-term, sustained incentive programs for ongoing ecosystem growth. [](https://docs.merkl.xyz/merkl-mechanisms/features#infinite-customizability-with-token-wrappers) 🎭 Infinite Customizability with Token Wrappers ------------------------------------------------------------------------------------------------------------------------------------------------------ Merkl campaigns can distribute tokens with custom properties, known as token wrappers, to introduce advanced incentive mechanisms. **Examples of Token Wrapper Use Cases:** * Vesting & Slashing Conditions: Add vesting schedules or penalties for early withdrawals. * Non-Prefunded Campaigns: Instead of preloading tokens, rewards are pulled from a multisig when users claim. * Time-Locked Transfers: Issue non-transferable tokens that unlock after a set period. * Redeemable Tokens: Distribute placeholder tokens that can be redeemed later. Merkl provides a suite of template contracts for token wrappers in the Merkl GitHub repository so anyone can build [its own token wrapper](https://github.com/AngleProtocol/merkl-contracts/tree/main/contracts/partners/tokenWrappers) . Some templates have already been audited by Merkl partners! Got a custom use case? Let us know—we’re happy to collaborate and help build your solution. [](https://docs.merkl.xyz/merkl-mechanisms/features#cross-chain-campaigns) 🌍 Cross-Chain Campaigns -------------------------------------------------------------------------------------------------------- Merkl allows you to incentivize activity on one chain while distributing rewards on another. **How It Works:** * Activity is tracked on Chain A (e.g., a protocol running on Arbitrum). * Rewards remain claimable on Chain B (e.g., distributed token stays on Ethereum): the chain where the token is claimable is the chain where the campaign was created **Why is this useful?** * Efficient token management: Keeps governance tokens on a single chain, reducing the need for bridging. * Cross-chain flexibility: Supports protocols that operate on multiple chains without fragmenting incentives.  Rewards sent on a different chain than the one where users perform the action to be eligible **Important considerations**: Some smart contracts on the chain you are incentivizing activity may not exist on the chain where users can claim their reward (or may exist at a different address): * Affected addresses will be unable to claim rewards in this case * Solution: As a campaign manager, you should blacklist any ineligible addresses to prevent reward loss. Or you can reallocate rewards (more below) of addresses that cannot claim to an address controlled by the same provider that can claim its rewards [](https://docs.merkl.xyz/merkl-mechanisms/features#retroactive-campaigns) ◀️ Retroactive Campaigns -------------------------------------------------------------------------------------------------------- You can create campaigns in the past to reward OG users. It can start and end in the past or it can end in the future. [](https://docs.merkl.xyz/merkl-mechanisms/features#campaign-management) Campaign Management ------------------------------------------------------------------------------------------------- Campaign managers can perform several actions on their live and past campaigns, including: * [Overriding live campaigns](https://docs.merkl.xyz/distribute-with-merkl/campaign-management#%EF%B8%8F-campaign-overrides) * [Cancelling existing campaigns](https://docs.merkl.xyz/distribute-with-merkl/campaign-management#-campaign-cancellation) * [Reallocating unclaimed rewards from past campaigns](https://docs.merkl.xyz/distribute-with-merkl/campaign-management#-campaign-reallocation) [PreviousCustomization Options](https://docs.merkl.xyz/merkl-mechanisms/customization-options) [NextCampaign Configuration](https://docs.merkl.xyz/merkl-mechanisms/campaignconfiguration) Last updated 1 month ago * [❌ Blacklisting](https://docs.merkl.xyz/merkl-mechanisms/features#blacklisting) * [✅ Whitelisting](https://docs.merkl.xyz/merkl-mechanisms/features#whitelisting) * [🔥 Run Multiple Campaigns on the Same Opportunity](https://docs.merkl.xyz/merkl-mechanisms/features#run-multiple-campaigns-on-the-same-opportunity) * [⏳ Campaigns of Any Duration](https://docs.merkl.xyz/merkl-mechanisms/features#campaigns-of-any-duration) * [🎭 Infinite Customizability with Token Wrappers](https://docs.merkl.xyz/merkl-mechanisms/features#infinite-customizability-with-token-wrappers) * [🌍 Cross-Chain Campaigns](https://docs.merkl.xyz/merkl-mechanisms/features#cross-chain-campaigns) * [◀️ Retroactive Campaigns](https://docs.merkl.xyz/merkl-mechanisms/features#retroactive-campaigns) * [Campaign Management](https://docs.merkl.xyz/merkl-mechanisms/features#campaign-management) --- # Create a campaign from a multisig or Gnosis Safe | Merkl Docs The recommended method for creating campaigns with Merkl using a multisig is through the Gnosis Safe Transaction Builder. This guide walks you through generating and executing the payload to finalize your campaign creation. [](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-a-multisig-or-gnosis-safe#id-1.-configure-your-campaign-and-get-your-payload) 1\. Configure Your Campaign and Get Your Payload ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- **For simple campaigns:** Follow [our guide](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign) to use Merkl Studio to configure your campaign. Once your configuration is complete, download your payload by clicking on _Using_  _SAFE wallet? Build a payload_ at the bottom of the last campaign creation step.  **For multiple or advanced campaigns:** If you're creating multiple campaigns at once or prefer a programmatic approach, refer to [this guide](https://docs.merkl.xyz/distribute-with-merkl/create-multiple-campaigns) . [](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-a-multisig-or-gnosis-safe#id-2.-upload-the-json-file) 2\. Upload the JSON File ------------------------------------------------------------------------------------------------------------------------------------------------------------- Once you have your JSON payload file, open the Gnosis Safe Transaction Builder and either drag and drop the file into the designated area, or click _Choose a file_ to upload it manually.  If you're using a different tool, proceed with your standard workflow. [](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-a-multisig-or-gnosis-safe#id-3.-execute-the-transactions) 3\. Execute the Transactions --------------------------------------------------------------------------------------------------------------------------------------------------------------------- You will see the following 3 transactions: * `approve`: Approves the MerklDistributor contract to spend your reward tokens * `acceptConditions`: Accepts Merkl's Terms & Conditions. This is required the first time you create a campaign but can be removed from subsequent payloads. * `createCampaign`: Creates the campaign  Click _Create Batch_ and then _Send Batch_ to execute the transactions and deploy your Merkl campaign. Congratulations! You have successfully created your Merkl campaign. Campaigns typically appear in the Merkl app within approximately 1 hour. You can view the latest created campaigns in [this filtered view](https://app.merkl.xyz/?sort=lastCampaignCreatedAt-desc&tokenType=all) . [](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-a-multisig-or-gnosis-safe#recommendations) Recommendations ----------------------------------------------------------------------------------------------------------------------------------------- **Optimize for Gas Fees:** You don't need to include `acceptConditions` for every campaign—including it only in your first campaign can help reduce gas fees. You can safely remove it from payloads generated by Merkl Studio or the Merkl API for subsequent campaigns. Similarly, for approval amounts: you can grant a large allowance once and then exclude the approval transaction from future payloads. **Handle Large Payloads:** On some chains, transaction payloads may be too large for the available block space, especially when creating multiple campaigns in a single payload. This occurs when the encoded campaign data exceeds the chain's transaction size limits. The limits vary by chain and depend on the number of campaigns and their complexity—some campaign types encode more data onchain than others. If your transaction fails due to payload size, you'll need to split it into multiple smaller payloads. Use our [Payload Splitter tool](https://splitter.merkl.xyz/) to automatically divide large payloads into executable batches. **Save for Future Use:** Save the transaction batch in your library to streamline the process and create new campaigns faster in the future. [PreviousCreate multiple campaigns](https://docs.merkl.xyz/distribute-with-merkl/create-multiple-campaigns) [NextCreate your campaign from a DAO](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-dao) Last updated 10 days ago * [1\. Configure Your Campaign and Get Your Payload](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-a-multisig-or-gnosis-safe#id-1.-configure-your-campaign-and-get-your-payload) * [2\. Upload the JSON File](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-a-multisig-or-gnosis-safe#id-2.-upload-the-json-file) * [3\. Execute the Transactions](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-a-multisig-or-gnosis-safe#id-3.-execute-the-transactions) * [Recommendations](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-a-multisig-or-gnosis-safe#recommendations) --- # Fee Model | Merkl Docs Merkl's fees are deducted directly from the incentives distributed by campaign creators. [](https://docs.merkl.xyz/distribute-with-merkl/fee-model#pay-as-you-go) Pay-as-You-Go ------------------------------------------------------------------------------------------- **Standard campaign fee**: 3% of distributed incentives **Airdrop discount**: JSON-based airdrops are charged at a reduced rate of 0.5% **Degressive fee structure**: The more you distribute (excluding airdrops), the lower your effective fee rate. This makes Merkl increasingly cost-efficient at scale. Fees are calculated based on the total amount distributed across all campaigns and addresses associated with your entity: * **3%** on the first $1M distributed * **2.25%** on amounts between $1M and $2.5M * **1.75%** on amounts between $2.5M and $5M * **1.5%** on amounts above $5M **Example**: If you distribute $3M in total, you'll pay 3% on the first $1M ($30k), 2.25% on the next $1.5M ($33.75k), and 1.75% on the final $500k ($8.75k), for a total fee of $72.5k (2.42% effective rate). [](https://docs.merkl.xyz/distribute-with-merkl/fee-model#commitment-model-for-high-volume-campaigns) Commitment Model (For High-Volume Campaigns) ------------------------------------------------------------------------------------------------------------------------------------------------------- For projects planning to distribute significant incentives, Merkl offers a 25% fee discount when you commit upfront to campaigns distributing more than $500k in total incentives. **How it works**: Pay your fees in advance for campaigns totaling at least $500k in distributions, and receive an automatic 25% reduction on those fees. Contact the Merkl team to discuss commitment model options and unlock volume discounts. [](https://docs.merkl.xyz/distribute-with-merkl/fee-model#unclaimed-rewards-policy) Unclaimed Rewards Policy ----------------------------------------------------------------------------------------------------------------- Campaign creators on Merkl can [freely reallocate](https://docs.merkl.xyz/distribute-with-merkl/campaign-management#campaign-management) all unclaimed rewards once their campaign ends. One year after the campaign's end, if the campaign creators have not previously reallocated rewards and if there remain unclaimed rewards, Merkl reserves the right to reclaim them. [PreviousCampaign Management](https://docs.merkl.xyz/distribute-with-merkl/campaign-management) [NextEarn rewards - User guide](https://docs.merkl.xyz/earn-with-merkl/earning-with-merkl) Last updated 1 month ago * [Pay-as-You-Go](https://docs.merkl.xyz/distribute-with-merkl/fee-model#pay-as-you-go) * [Commitment Model (For High-Volume Campaigns)](https://docs.merkl.xyz/distribute-with-merkl/fee-model#commitment-model-for-high-volume-campaigns) * [Unclaimed Rewards Policy](https://docs.merkl.xyz/distribute-with-merkl/fee-model#unclaimed-rewards-policy) --- # Branding and Integration | Merkl Docs All Merkl branding assets for using Merkl as a white-label solution, along with communication materials, can be found [here](https://merkl.xyz/brand) . [PreviousDisplay Your Native APR](https://docs.merkl.xyz/integrate-merkl/nativeapr) [NextSmart Contract Addresses](https://docs.merkl.xyz/integrate-merkl/smart-contract-addresses) Last updated 8 months ago --- # Before you start | Merkl Docs [](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#merkls-core-principles) ⚙️ Merkl’s core principles ------------------------------------------------------------------------------------------------------------------------ Before setting up your campaign on Merkl, make sure you have read and understood: * [**Merkl’s reward distribution process**](https://docs.merkl.xyz/merkl-mechanisms/technical-overview) (reward computation vs. reward update, dispute period, etc.) * [**The different incentive mechanisms**](https://docs.merkl.xyz/merkl-mechanisms/incentive-mechanisms) (campaign types, distribution types, scoring types) * How to personalize your campaign using [**customization options**](https://docs.merkl.xyz/merkl-mechanisms/customization-options) * [**Merkl forwarding system**](https://docs.merkl.xyz/merkl-mechanisms/reward-forwarding) * [What the **configuration** of a campaign is](https://docs.merkl.xyz/merkl-mechanisms/campaignconfiguration) * [**Additional features**](https://docs.merkl.xyz/merkl-mechanisms/features) that can make your campaign unique If you're looking for some incentive mechanism for which you're not sure about whether it's supported, or looking to add incentive features or customization options that are not displayed on the platform, please contact us! Some Merkl features (e.g., new distribution types, campaign types, customization options) may not be directly available in the campaign creation flow. If a required configuration option is not available in the frontend, make sure to check [our docs for advanced campaign creation](https://docs.merkl.xyz/distribute-with-merkl/create-multiple-campaigns) . [](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#token-whitelisting) 📝 Token whitelisting --------------------------------------------------------------------------------------------------------------- Before starting your campaign, you need to ensure that the token you want to use as reward with Merkl has been whitelisted. We usually process token whitelisting requests once a day, and it's a way for us to ensure that we will be able to properly compute APRs and that the token will be safe to use for our users. **Campaigns must distribute at least ~$1/hour in total rewards to avoid dusting.** You can check whether your token is already whitelisted by setting it as the reward token in the [Merkl studio](https://studio.merkl.xyz/create-campaign/clamm) . If your token is not whitelisted, please submit the reward token’s price source and logo by filling out this [whitelisting form](https://anglemoney.notion.site/1aecfed0d48c808a8194fe2befd50bdb?pvs=105) . Make sure you have all the tokens you want to distribute in your wallet when creating a campaign [](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#campaign-launch-flow) Campaign launch flow ---------------------------------------------------------------------------------------------------------------- When creating your first campaign with Merkl, keep in mind that it may take up to **1 hour** for the campaign to become visible on the Merkl app. It's normal for TVLs and APRs to show as 0 when your campaign first appears. In most cases, the Merkl system dynamically fetches and updates these values every 10 minutes, but for complex campaigns, it may require an engine computation cycle (up to 2 hours) to accurately calculate and display TVLs, as described in the [technical overview](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#tvl) . It's also expected for **your campaign's leaderboard to appear empty right after launch**. The Merkl Engine needs time to perform [the necessary computations](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-computation) before this data becomes available. The first rewards typically become claimable approximately 8 hours after campaign creation, though pending rewards should appear within 2 hours after they start. [](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#test-campaigns) 🧪 Test campaigns ------------------------------------------------------------------------------------------------------- You may want to start testing the flow and integrating our data before your point program starts. Merkl is not deployed on testnets, but you can still run test campaigns using our test token: **aglaMerkl**. These test campaigns are not mandatory — they're available to help you experiment with how Merkl works using valueless tokens, so you can better prepare your upcoming campaigns. However, since they consume computation resources on our end, we encourage you to use this feature only when there's a clear need. Note that test campaigns will **not appear on the Merkl app** and will not be visible to users, as they are automatically filtered out from the interface. To get started, send us a message and we'll provide you with our test token. aglaMerkl has no value and is only intended for creating test campaigns on Merkl. You can then create your test campaign using aglaMerkl tokens. While the campaign won't show up in the Merkl app, you'll be able to **check everything is working properly via the Merkl API**, using the campaign ID generated at creation. You can refer to the [API integration page](https://docs.merkl.xyz/integrate-merkl/app) for how to effectively use the API. Make sure to verify that: * distribution is functioning as expected * key metrics like TVL are correctly computed If everything looks good in the API, it will appear correctly in the Merkl front end once the real campaign is live! If you need help to create your first test campaigns, feel free to reach out to us. [](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#what-budget-should-i-set-for-my-campaign) 💰 What budget should I set for my campaign? ------------------------------------------------------------------------------------------------------------------------------------------------------------ The ideal campaign budget depends on your specific objectives and the distribution method you choose. Campaign budgets follow a natural supply-and-demand dynamic: liquidity providers want to maximize their rewards, while campaign creators aim to minimize costs. As a result, TVL typically scales proportionally with the reward budget you allocate. Depending on your campaign type, you need to account for fees differently (see our [fees section](https://docs.merkl.xyz/distribute-with-merkl/fee-model) for details). **Distribution methods matter**: If you're concerned about over-distributing rewards early in your campaign, consider using a [capped APR campaign](https://docs.merkl.xyz/merkl-mechanisms/distributions#-capped-reward-rate-campaigns) . This approach ensures you don't exhaust your budget too quickly if TVL starts low, as rewards are distributed at a fixed rate relative to TVL rather than depleting a fixed token amount. **Benchmarking APRs**: To gauge appropriate reward levels, you can: * Browse existing campaigns on the [Merkl app](https://app.merkl.xyz/) to see typical APRs in your category * Use Merkl's [APR simulation tool](https://docs.google.com/spreadsheets/d/1suPzoiFfZP3_XdXNu9qh63gNUbbXaWoKuhy17FRCEIc/edit?usp=sharing) to model how different reward budgets translate to APRs at various TVL levels. To use this tool, you may simply duplicate the sheet and input your own numbers to simulate. * Adjust your budget based on competitive rates and your growth targets **Start small, iterate often**: We recommend launching shorter campaigns initially (e.g., 2 weeks) to test performance and gather data. You can then create follow-up campaigns with optimized parameters based on actual TVL, user engagement, and APR effectiveness. This iterative approach minimizes risk and maximizes ROI. [](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#merkl-terms) 📃 Merkl terms ------------------------------------------------------------------------------------------------- You must also make sure that you have read and understood [Merkl's Terms & Conditions](https://app.merkl.xyz/terms) . You will be required to agree to these terms during the campaign setup process. [PreviousGlossary](https://docs.merkl.xyz/merkl-mechanisms/glossary) [NextCreate a campaign](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign) Last updated 1 month ago * [⚙️ Merkl’s core principles](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#merkls-core-principles) * [📝 Token whitelisting](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#token-whitelisting) * [Campaign launch flow](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#campaign-launch-flow) * [🧪 Test campaigns](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#test-campaigns) * [💰 What budget should I set for my campaign?](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#what-budget-should-i-set-for-my-campaign) * [📃 Merkl terms](https://docs.merkl.xyz/distribute-with-merkl/before-you-start#merkl-terms) --- # Distribution Types | Merkl Docs **Distribution types** define the reward distribution model and how the total campaign budget is spent over time. They determine the economic structure of your campaign—whether you distribute a fixed budget proportionally, offer guaranteed APRs, or cap maximum returns. Merkl supports various distribution models, allowing campaign creators to choose the approach that best fits their incentive goals and budget constraints.  [](https://docs.merkl.xyz/merkl-mechanisms/distributions#variable-reward-rate-campaigns) 📈 Variable Reward Rate Campaigns ------------------------------------------------------------------------------------------------------------------------------- In variable reward rate campaigns, rewards are distributed proportionally based on time-weighted liquidity within the eligibility pool. This is the most classical form of campaign. ### [](https://docs.merkl.xyz/merkl-mechanisms/distributions#key-characteristics) Key Characteristics * Constant reward rate for campaign creators: A fixed amount of tokens is distributed per second, regardless of liquidity changes. * Variable APR for participants: As more users join, rewards per user decrease (like slicing a fixed-size pizza into more pieces). * Prefunded & fixed duration: The full campaign budget is deposited upfront, and the campaign runs for a set time. ### [](https://docs.merkl.xyz/merkl-mechanisms/distributions#example-liquidity-pool-incentives) Example: Liquidity Pool Incentives Imagine an incentive program targeting liquidity in a pool: * Day Start: Two LPs each contribute $100 (50%/50%). * Midday: A third LP adds $200 (total pool: $400). As a result: * The first two LPs each get 50 tokens for their contribution in the first half of the day, then 25 tokens each for the second half. * The third LP, who contributed $200 in the second half, receives 50% of the rewards for that period, which is 50 tokens. Result: Early participants earn more rewards before new LPs enter, while later participants dilute the total yield for others. ### [](https://docs.merkl.xyz/merkl-mechanisms/distributions#anti-dos-measures) Anti DoS Measures To prevent excessive computational load and spam, Merkl applies an anti-DoS filter to Variable APR campaigns. * Users earning less than 0.000001% of total campaign rewards per engine run are excluded. * This prevents micro-distributions that could disrupt system performance. Example: Uniswap V2 Liquidity Pool Campaign * Campaign Duration: 14 days * Total Value Locked (TVL): $1,000,000 (on Arbitrum) * Merkl Engine Run Frequency: Every 4 hours (6 times per day) For this campaign: * Each reward distribution releases 1/84th of the total rewards (1 / (14 days × 6 runs per day)). * If a user provides $10 of liquidity, they represent 1/100,000th (0.001%) of the total TVL ($10 / $1,000,000). * Per engine run, their potential reward would be 1/8,400,000th (0.000012%) of the total rewards (1/100,000 × 1/84). * Since this is above the 1/100,000,000th (0.000001%) threshold, the reward would be distributed. However, if the TVL increased to $20,000,000, the same user’s share would drop to 1/2,000,000th (0.00005%), and their per-run reward would be 1/16,800,000th (0.0000006%), below the threshold. As a result, they would not receive rewards. [](https://docs.merkl.xyz/merkl-mechanisms/distributions#fixed-reward-rate-campaigns) 🔒 Fixed Reward Rate Campaigns ------------------------------------------------------------------------------------------------------------------------- In fixed reward rate campaigns, users earn a predefined amount of rewards per unit of liquidity at a set rate. ### [](https://docs.merkl.xyz/merkl-mechanisms/distributions#key-characteristics-1) Key Characteristics * Constant reward rate per users: Users receive a fixed APR regardless of total liquidity. * Variable cost for campaign creators: As more users join, the overall cost increases, but individual earnings remain stable. * Campaign may finish earlier: Campaigns end when funds are depleted or when the scheduled duration expires. If a campaign runs out of funds before its end date, rewards are split proportionally (like a variable reward rate campaign) in the final run. If the campaign ends early, unused rewards are returned to the campaign creator. **There are two types of fixed reward rate campaigns, depending on whether the distributed amount is pegged to a fixed token amount or to a fixed dollar value.** * **Fixed token reward** * Users earn a fixed amount of tokens, regardless of token price variations * Users’ APR is correlated to token reward’s price change * Total rewards amount may or may not be fully spent, depending of user’s participation * **Fixed dollar reward** * Users earn a fixed amount of dollars (distributed in tokens) * APR in dollars is fixed for users (but the token amount may vary) * The amount of token distributed adjusts with token price variations (but the USD-denominated value is fixed) ### [](https://docs.merkl.xyz/merkl-mechanisms/distributions#example-fixed-reward-rate-campaign) Example: Fixed Reward Rate Campaign A campaign offers $1 in rewards per $100 in liquidity per day - which makes a 365% fixed APR. * If TVL = $100, the cost is $1 per day. * If TVL = $100 million, the cost for the campaign creator scales to $1M per day. You can also incentivize by the number of tokens held. Let's say that Bob wants to incentivize holding _LONG_ and he doesn't know how to price it. A campaign can offer $1 in rewards per 100 _LONG_ held per day. [](https://docs.merkl.xyz/merkl-mechanisms/distributions#capped-reward-rate-campaigns) 📉 Capped Reward Rate Campaigns --------------------------------------------------------------------------------------------------------------------------- Capped reward rate campaigns work like variable rate campaigns, but the campaign creator sets a maximum APR that cannot be exceeded, ensuring users are never overpaid. ### [](https://docs.merkl.xyz/merkl-mechanisms/distributions#key-characteristics-2) Key Characteristics * Rewards are fully distributed across the entire campaign duration. * APR adjusts according to TVL: the higher the TVL, the lower the APR. * APR cannot exceed the maximum set by the campaign creator. This prevents users from capturing excessive rewards, especially early in the campaign when TVL is low. ### [](https://docs.merkl.xyz/merkl-mechanisms/distributions#example-capped-reward-rate-campaign) Example: Capped Reward Rate Campaign A protocol launches a 4-week campaign with a total reward budget of 10,000 tokens to distribute. The APR is capped at 15%. At the start of the campaign, the TVL averages around $150,000. Based on this TVL, the APR would normally be 20%, which would distribute approximately 576 tokens per week. However, due to the 15% APR cap, the actual APR is limited to 15%, resulting in fewer tokens distributed per week than the uncapped rate. In week 3, TVL increases sharply to $500,000. As TVL rises, the APR adjusts downward accordingly, staying below the 15% cap. This ensures the campaign budget is distributed evenly and sustainably over the full 4 weeks. [PreviousStaking & Restaking Campaigns](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/staking) [NextScoring Types](https://docs.merkl.xyz/merkl-mechanisms/scoring) Last updated 1 month ago * [📈 Variable Reward Rate Campaigns](https://docs.merkl.xyz/merkl-mechanisms/distributions#variable-reward-rate-campaigns) * [Key Characteristics](https://docs.merkl.xyz/merkl-mechanisms/distributions#key-characteristics) * [Example: Liquidity Pool Incentives](https://docs.merkl.xyz/merkl-mechanisms/distributions#example-liquidity-pool-incentives) * [Anti DoS Measures](https://docs.merkl.xyz/merkl-mechanisms/distributions#anti-dos-measures) * [🔒 Fixed Reward Rate Campaigns](https://docs.merkl.xyz/merkl-mechanisms/distributions#fixed-reward-rate-campaigns) * [Key Characteristics](https://docs.merkl.xyz/merkl-mechanisms/distributions#key-characteristics-1) * [Example: Fixed Reward Rate Campaign](https://docs.merkl.xyz/merkl-mechanisms/distributions#example-fixed-reward-rate-campaign) * [📉 Capped Reward Rate Campaigns](https://docs.merkl.xyz/merkl-mechanisms/distributions#capped-reward-rate-campaigns) * [Key Characteristics](https://docs.merkl.xyz/merkl-mechanisms/distributions#key-characteristics-2) * [Example: Capped Reward Rate Campaign](https://docs.merkl.xyz/merkl-mechanisms/distributions#example-capped-reward-rate-campaign) --- # Glossary | Merkl Docs [](https://docs.merkl.xyz/merkl-mechanisms/glossary#apr) [APR](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#apr) ------------------------------------------------------------------------------------------------------------------------------------ [](https://docs.merkl.xyz/merkl-mechanisms/glossary#blacklist) [Blacklist](https://docs.merkl.xyz/merkl-mechanisms/features#blacklisting) ----------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#boost) [Boost](https://docs.merkl.xyz/merkl-mechanisms/customization-options#boosts) ---------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#campaign) [Campaign](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#opportunity-vs.-campaign) ------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#capped-reward-rate-campaign) [Capped reward rate campaign](https://docs.merkl.xyz/merkl-mechanisms/distributions#capped-reward-rate-campaigns) -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#customization-option) [Customization option](https://docs.merkl.xyz/merkl-mechanisms/customization-options) --------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#cross-chain-rewards) [Cross-chain rewards](https://docs.merkl.xyz/merkl-mechanisms/features#cross-chain-campaigns) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#daily-rewards) [Daily rewards](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#daily-rewards) ------------------------------------------------------------------------------------------------------------------------------------------------------------------ [](https://docs.merkl.xyz/merkl-mechanisms/glossary#dashboard-merkl-app) [Dashboard (Merkl App)](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#merkl-app) ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#dashboard-merkl-studio) [Dashboard (Merkl Studio)](https://docs.merkl.xyz/distribute-with-merkl/campaign-management) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ [](https://docs.merkl.xyz/merkl-mechanisms/glossary#dispute) [Dispute](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#dispute-period-and-process) ------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#eligibility) [Eligibility](https://docs.merkl.xyz/merkl-mechanisms/customization-options#eligibility) --------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#encompassing-campaign) [Encompassing campaign](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/encompassing) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#fixed-reward-rate-campaign) [Fixed reward rate campaign](https://docs.merkl.xyz/merkl-mechanisms/distributions#fixed-reward-rate-campaigns) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#forwarder) [Forwarder](https://docs.merkl.xyz/merkl-mechanisms/reward-forwarding) ------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#linked-opportunities) [Linked opportunities](https://docs.merkl.xyz/merkl-mechanisms/reward-forwarding#linked-opportunities) -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#merkl-app) [Merkl App](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#merkl-app) ------------------------------------------------------------------------------------------------------------------------------------------------------ [](https://docs.merkl.xyz/merkl-mechanisms/glossary#merkl-studio) [Merkl Studio](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#merkl-studio) --------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#net-lending-and-borrowing) [Net lending & borrowing](https://docs.merkl.xyz/merkl-mechanisms/campaign-types/lending-borrowing#preventing-lending-loops) ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#opportunity) [Opportunity](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#opportunity-vs.-campaign) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#point-program) [Point program](https://docs.merkl.xyz/distribute-with-merkl/create-a-point-program) ------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#pre-tge) [Pre-TGE](https://docs.merkl.xyz/distribute-with-merkl/create-a-pretge-campaign) --------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#referral) [Referral](https://docs.merkl.xyz/merkl-mechanisms/customization-options#referral-program) -------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#reward-compute) [Reward compute](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-computation) ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#reward-update) [Reward update](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#reward-updates) ------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#tvl) [TVL](https://docs.merkl.xyz/merkl-mechanisms/technical-overview#tvl) ------------------------------------------------------------------------------------------------------------------------------------ [](https://docs.merkl.xyz/merkl-mechanisms/glossary#variable-reward-rate-campaign) [Variable reward rate campaign](https://docs.merkl.xyz/merkl-mechanisms/distributions#variable-reward-rate-campaigns) -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- [](https://docs.merkl.xyz/merkl-mechanisms/glossary#whitelist) [Whitelist](https://docs.merkl.xyz/merkl-mechanisms/features#whitelisting) ----------------------------------------------------------------------------------------------------------------------------------------------- [PreviousCampaign Configuration](https://docs.merkl.xyz/merkl-mechanisms/campaignconfiguration) [NextBefore you start](https://docs.merkl.xyz/distribute-with-merkl/before-you-start) Last updated 1 month ago * [APR](https://docs.merkl.xyz/merkl-mechanisms/glossary#apr) * [Blacklist](https://docs.merkl.xyz/merkl-mechanisms/glossary#blacklist) * [Boost](https://docs.merkl.xyz/merkl-mechanisms/glossary#boost) * [Campaign](https://docs.merkl.xyz/merkl-mechanisms/glossary#campaign) * [Capped reward rate campaign](https://docs.merkl.xyz/merkl-mechanisms/glossary#capped-reward-rate-campaign) * [Customization option](https://docs.merkl.xyz/merkl-mechanisms/glossary#customization-option) * [Cross-chain rewards](https://docs.merkl.xyz/merkl-mechanisms/glossary#cross-chain-rewards) * [Daily rewards](https://docs.merkl.xyz/merkl-mechanisms/glossary#daily-rewards) * [Dashboard (Merkl App)](https://docs.merkl.xyz/merkl-mechanisms/glossary#dashboard-merkl-app) * [Dashboard (Merkl Studio)](https://docs.merkl.xyz/merkl-mechanisms/glossary#dashboard-merkl-studio) * [Dispute](https://docs.merkl.xyz/merkl-mechanisms/glossary#dispute) * [Eligibility](https://docs.merkl.xyz/merkl-mechanisms/glossary#eligibility) * [Encompassing campaign](https://docs.merkl.xyz/merkl-mechanisms/glossary#encompassing-campaign) * [Fixed reward rate campaign](https://docs.merkl.xyz/merkl-mechanisms/glossary#fixed-reward-rate-campaign) * [Forwarder](https://docs.merkl.xyz/merkl-mechanisms/glossary#forwarder) * [Linked opportunities](https://docs.merkl.xyz/merkl-mechanisms/glossary#linked-opportunities) * [Merkl App](https://docs.merkl.xyz/merkl-mechanisms/glossary#merkl-app) * [Merkl Studio](https://docs.merkl.xyz/merkl-mechanisms/glossary#merkl-studio) * [Net lending & borrowing](https://docs.merkl.xyz/merkl-mechanisms/glossary#net-lending-and-borrowing) * [Opportunity](https://docs.merkl.xyz/merkl-mechanisms/glossary#opportunity) * [Point program](https://docs.merkl.xyz/merkl-mechanisms/glossary#point-program) * [Pre-TGE](https://docs.merkl.xyz/merkl-mechanisms/glossary#pre-tge) * [Referral](https://docs.merkl.xyz/merkl-mechanisms/glossary#referral) * [Reward compute](https://docs.merkl.xyz/merkl-mechanisms/glossary#reward-compute) * [Reward update](https://docs.merkl.xyz/merkl-mechanisms/glossary#reward-update) * [TVL](https://docs.merkl.xyz/merkl-mechanisms/glossary#tvl) * [Variable reward rate campaign](https://docs.merkl.xyz/merkl-mechanisms/glossary#variable-reward-rate-campaign) * [Whitelist](https://docs.merkl.xyz/merkl-mechanisms/glossary#whitelist) --- # Smart Contract Addresses | Merkl Docs All Merkl smart contract addresses, categorized by chain are listed [here](https://app.merkl.xyz/status) . On the vast majority of chains, the Distributor is deployed at `0x3Ef3D8bA38EBe18DB133cEc108f4D14CE00Dd9Ae` and the Campaign Creator is deployed at `0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd`. [PreviousBranding and Integration](https://docs.merkl.xyz/integrate-merkl/branding-and-integration) Last updated 6 months ago --- # Create a campaign | Merkl Docs Merkl Studio is your command center to launch, manage, and optimize incentive campaigns. This guide walks you through the process of creating a campaign step by step. Merkl Studio doesn't support all campaign types and customization options offered by Merkl. If you need features not available in the Studio or have questions, please reach out to us. [](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#step-by-step-guide) Step-by-Step Guide ------------------------------------------------------------------------------------------------------------- ### [](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-1.-connect-your-wallet) 1\. Connect Your Wallet Connect the wallet holding the rewards you want to distribute. Ensure you're connected to the chain where you want to distribute rewards. To see all supported chains, check the [Status page](https://app.merkl.xyz/status) in the Merkl App.   You can create cross-chain campaigns with Merkl—incentivize an asset on one chain while distributing rewards on another (e.g., incentivize a WETH-USDC pool on Ethereum by distributing WBTC on Base). ### [](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-2.-click-create-campaign) 2\. Click Create Campaign Click the _Create Campaign_ button to begin setting up your campaign.  ### [](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-3.-select-your-incentive-category) 3\. Select Your Incentive Category Choose your incentive category by clicking on the appropriate card.  To incentivize Aave lending positions, Uniswap V2, or similar liquidity pools, use the _Token Holding_ campaign category. ### [](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-4.-configure-your-rewards) 4\. Configure Your Rewards Fill out campaign details including the asset to incentivize, the asset type (token or point), the reward amount to distribute, start date, end date, and more. The required details depend on the campaign type you selected. For detailed explanations of each parameter, see the [campaign types page](https://docs.merkl.xyz/merkl-mechanisms/campaign-types) .  The total rewards amount represents the total to be distributed over the entire campaign duration (a maintenance fee may be applied on top). Merkl sets a minimum token amount that can be distributed per hour for each reward token. If your token amount is too low (typically less than $1 per hour), you will not be able to create your campaign. ### [](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-5.-set-restrictions) 5\. Set Restrictions This section allows you to configure blacklists and/or whitelists for your campaign. Blacklisted addresses won't receive any rewards, while whitelisted addresses will be the only addresses eligible for rewards (excluding all others).  ### [](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-6.-personalize-your-campaign) 6\. Personalize Your Campaign Campaigns on Merkl can be fully customized to your needs. You can apply customization options such as boosts and more. New options are constantly being added! Check out the [Customization options page](https://docs.merkl.xyz/merkl-mechanisms/customization-options) for a comprehensive list of available options.  You may also be asked to provide a deposit URL—the link where users can interact with the asset you want to incentivize (e.g., a lending market, liquidity pool, etc.). Since Merkl is non-custodial, users must interact directly with protocols to be eligible for rewards. Merkl does not hold any user funds. ### [](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-7.-review-campaign-and-accept-terms) 7\. Review Campaign and Accept Terms Double-check all the information. Once you're ready, click the _Accept Terms_ button and confirm in your wallet.  ### [](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-8.-approve-and-launch) 8\. Approve and Launch Approve the reward token transfer from your wallet to Merkl, then create the campaign by signing the transaction. You can sign and submit using either an EOA (externally owned account) or a multisig wallet. Regardless of the method you choose, you will need to complete these 3 steps: * Accept the Terms & Conditions * Approve the tokens for transfer * Deposit the tokens #### [](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#using-an-eoa) Using an EOA * Double-check your campaign configuration * Read and accept Merkl's Terms & Conditions by clicking the _Accept_ button and signing with your wallet * Approve the tokens for transfer and deposit the amount you want to distribute, plus [the standard Merkl fees](https://docs.merkl.xyz/distribute-with-merkl/fee-model) #### [](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#using-a-multisig-wallet-safe) Using a Multisig Wallet (Safe) The recommended method for distributing rewards with Merkl using a multisig is through the Gnosis Safe Transaction Builder. To learn how to deploy your campaign from a multisig, see [this guide](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-a-multisig-or-gnosis-safe) . Once you've executed your transaction, your campaign may take up to **one hour** to become visible on the frontend after creation. [PreviousBefore you start](https://docs.merkl.xyz/distribute-with-merkl/before-you-start) [NextCreate multiple campaigns](https://docs.merkl.xyz/distribute-with-merkl/create-multiple-campaigns) Last updated 1 month ago * [Step-by-Step Guide](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#step-by-step-guide) * [1\. Connect Your Wallet](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-1.-connect-your-wallet) * [2\. Click Create Campaign](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-2.-click-create-campaign) * [3\. Select Your Incentive Category](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-3.-select-your-incentive-category) * [4\. Configure Your Rewards](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-4.-configure-your-rewards) * [5\. Set Restrictions](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-5.-set-restrictions) * [6\. Personalize Your Campaign](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-6.-personalize-your-campaign) * [7\. Review Campaign and Accept Terms](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-7.-review-campaign-and-accept-terms) * [8\. Approve and Launch](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign#id-8.-approve-and-launch) --- # Display Your Native APR | Merkl Docs Merkl enables protocols to display their native APR directly on the Merkl frontend alongside Merkl incentive APRs. This integration provides users with a comprehensive view of total returns available on your protocol. [](https://docs.merkl.xyz/integrate-merkl/nativeapr#overview) Overview --------------------------------------------------------------------------- By integrating your native APR data, you can: * Display protocol-specific APRs (e.g., lending yields, staking rewards, pool fees) on Merkl's frontend * Help users understand the full return potential when combining native yields with Merkl incentives * Increase visibility and transparency for your protocol's offerings  Native APR integration within Merkl frontend [](https://docs.merkl.xyz/integrate-merkl/nativeapr#implementation) Implementation --------------------------------------------------------------------------------------- ### [](https://docs.merkl.xyz/integrate-merkl/nativeapr#endpoint-requirements) Endpoint Requirements To integrate your native APR data, you must create and host a public API endpoint that returns APR data in the following JSON format: ### [](https://docs.merkl.xyz/integrate-merkl/nativeapr#field-descriptions) Field Descriptions * **title**: A clear, descriptive name for the APR type (e.g., "Aave Supply APR", "Compound Borrow APR", "Uniswap V3 Fee APR") * **opportunityId**: The unique identifier for the Merkl opportunity. To identify the correct `opportunityId` values for your protocol's opportunities, you can query the Merkl API to retrieve opportunity Ids for the opportunities related to your protocol. * **timestamp**: When the APR value was last calculated or updated, in Unix timestamp format (seconds) * **value**: The APR value as a percentage. For example, use `5.5` to represent 5.5% APR * **description** (optional): Additional information about how the APR is calculated or what it represents ### [](https://docs.merkl.xyz/integrate-merkl/nativeapr#next-steps) Next Steps Once you have prepared your endpoint: 1. Test your endpoint to ensure it returns data in the correct format 2. Verify that all opportunity IDs are accurate 3. Contact the Merkl team to register your endpoint and complete the integration **Important**: All APR data must be accurate and verifiable. Providing misleading, incorrect, or manipulated data will result in immediate removal of your integration from the Merkl frontend. Ensure that: * APR calculations are accurate and reflect actual protocol performance * Timestamps are current and updated regularly * Values are consistently formatted as percentages If you have questions or need assistance, please reach out to the Merkl team. [PreviousIntegrate Merkl API](https://docs.merkl.xyz/integrate-merkl/app) [NextBranding and Integration](https://docs.merkl.xyz/integrate-merkl/branding-and-integration) Last updated 1 month ago * [Overview](https://docs.merkl.xyz/integrate-merkl/nativeapr#overview) * [Implementation](https://docs.merkl.xyz/integrate-merkl/nativeapr#implementation) * [Endpoint Requirements](https://docs.merkl.xyz/integrate-merkl/nativeapr#endpoint-requirements) * [Field Descriptions](https://docs.merkl.xyz/integrate-merkl/nativeapr#field-descriptions) * [Next Steps](https://docs.merkl.xyz/integrate-merkl/nativeapr#next-steps) Copy [\ {\ "title": "Protocol Name APR", // Required: String - Display name for the APR (e.g., "Aave Supply APR", "Uniswap Fee APR")\ "opportunityId": "123...abc", // Required: String - The Merkl Opportunity ID this APR corresponds to\ "timestamp": 1716900000, // Required: Number - Unix timestamp in seconds when the APR was calculated\ "value": 5.5, // Required: Number - The APR as a percentage (e.g., 5.5 for 5.5%)\ "description": "Optional details" // Optional: String - Additional context about the APR calculation\ },\ {\ "title": "Protocol Name APR",\ "opportunityId": "0x456...def",\ "timestamp": 1716900000,\ "value": 12.4\ }\ ] --- # Create a campaign pre-TGE | Merkl Docs Merkl enables you to distribute tokens before they become transferable at TGE. This approach combines the best of both worlds: users can claim actual tokens (not just points), while you maintain control over transferability until your TGE. **How this differs from standard campaigns**: The distributed token is initially non-transferable but becomes fully transferable at TGE. Users can claim their tokens through the Merkl UI and see them in their wallets—they just can't transfer them yet. **How this differs from points campaigns**: There's no need for a separate airdrop later. Tokens earned by users are real tokens that automatically convert 1:1 to transferable tokens at TGE. Users already hold the tokens; they simply gain transferability at launch. [](https://docs.merkl.xyz/distribute-with-merkl/create-a-pretge-campaign#how-it-works) How it works -------------------------------------------------------------------------------------------------------- 1. **Whitelist Merkl contracts**: Grant permission to Merkl's `Creator` and `Distributor` contracts so they can distribute your non-transferable tokens. 2. **Create your campaigns**: Use Merkl's standard campaign creation flow to define reward rates, multipliers, and which onchain actions to track. Campaigns can be [created programmatically](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign) with simple scripts. 3. **Users claim tokens**: Participants interact onchain as usual and claim their non-transferable tokens directly through their Merkl dashboard. These tokens appear in their wallets immediately. [](https://docs.merkl.xyz/distribute-with-merkl/create-a-pretge-campaign#benefits) Benefits ------------------------------------------------------------------------------------------------ With this setup, you benefit from **all of Merkl's built-in features**: * **Public visibility**: Your campaigns appear in [the Merkl app](https://app.merkl.xyz/?tokenType=PRETGE&sort=tvl-desc) under the Pre-TGE section * **Leaderboards**: Users can track their rankings and performance * **APR displays**: Merkl can assign an estimated value to your tokens directly in the UI, showing users estimated APRs when farming. This estimate is typically based on your latest fundraising valuation or the agreed price with a CEX for an upcoming listing. * **Full customization**: Access to all of Merkl's [customization options](https://docs.merkl.xyz/merkl-mechanisms/customization-options) , including boosts, referral programs, and eligibility rules  Pre-TGE token campaigns appear in the Merkl app under the Pre-TGE section This is the most straightforward way to leverage Merkl's full feature set while maintaining control over token transferability until your TGE. No separate airdrop needed—users already hold the tokens. [](https://docs.merkl.xyz/distribute-with-merkl/create-a-pretge-campaign#pricing) Pricing ---------------------------------------------------------------------------------------------- The pricing for pre-TGE campaigns is the [same as campaigns distributing transferable tokens with Merkl](https://docs.merkl.xyz/distribute-with-merkl/fee-model) . [PreviousCreate a point program](https://docs.merkl.xyz/distribute-with-merkl/create-a-point-program) [NextCampaign Management](https://docs.merkl.xyz/distribute-with-merkl/campaign-management) Last updated 2 months ago * [How it works](https://docs.merkl.xyz/distribute-with-merkl/create-a-pretge-campaign#how-it-works) * [Benefits](https://docs.merkl.xyz/distribute-with-merkl/create-a-pretge-campaign#benefits) * [Pricing](https://docs.merkl.xyz/distribute-with-merkl/create-a-pretge-campaign#pricing) --- # Create your campaign from a DAO | Merkl Docs You can create campaigns directly using onchain smart contracts with Merkl. This guide covers different methods for doing so. [](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-dao#prerequisites) Prerequisites --------------------------------------------------------------------------------------------------------------- All methods require generating the associated [campaign configuration](https://docs.merkl.xyz/merkl-mechanisms/campaignconfiguration) and data for your campaigns. To retrieve the necessary campaign data and parameters, check our guides for using [Merkl Studio](https://docs.merkl.xyz/distribute-with-merkl/create-a-campaign) or [the Merkl APIs programmatically](https://docs.merkl.xyz/distribute-with-merkl/create-multiple-campaigns) . In either case, the campaign data can be found in the campaign JSON payload you would receive when creating campaigns from a multisig. [](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-dao#from-an-onchain-gauge-system) From an Onchain Gauge System --------------------------------------------------------------------------------------------------------------------------------------------- Many protocols rely on gauge systems where users vote onchain to determine the allocation of governance token rewards. Merkl offers a set of plugins to facilitate the integration of Merkl campaign creation within such systems. These plugins combine Merkl's flexibility and reporting features with the advantages of a fully automated onchain setup. ### [](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-dao#how-it-works) How It Works These plugins are smart contracts that expose the same interfaces as standard staking contracts for creating new campaigns (like `notifyReward`). When called, these contracts receive the reward tokens (via `transferFrom`) and create Merkl campaigns directly based on pre-set parameters. For these plugins to work, they must first be initialized with campaign data—such as which pool to incentivize, duration, blacklist/whitelist settings, and other parameters. Once set up, campaigns can be created automatically (e.g., weekly) by a bot with no trust assumptions—the process can even be made permissionless. Each week, based on DAO votes or the voting contract configuration, the plugin uses predefined parameters and updates the reward amount (based on voting results) and start timestamps when called. An example plugin can be found [here](https://github.com/AngleProtocol/merkl-contracts/blob/main/contracts/partners/middleman/MerklGaugeMiddlemanTemplate.sol) . Other teams have also developed different implementations. Check out these examples: * [Quickswap](https://polygonscan.com/address/0x3a381497813208508689d78c90EC9fb115D5640d#code) * [CrossCurve implementation](https://arbiscan.io/address/0xb665d0B69e91F596B9Dee3016e49136335993Fb8#readProxyContract) ### [](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-dao#step-by-step-guide) Step-by-Step Guide **1\. Update the Plugin Contract Interface** The plugin example assumes that the voting contract calls the gauge with the `notifyReward` function. Your voting contract may call associated gauges with different parameters. Ensure that the interface exposed by the plugin contract matches the one used by your other gauges. Your onchain governance may only support one reward token instead of multiple. You may need to update the plugin contract accordingly, as the Merkl template is designed to accommodate multiple reward tokens. Note: Depending on your voting contract setup, you can deploy one contract for all of your gauges. **2\. Define Your Campaign Parameters** Once your contract is deployed, pre-format your campaigns using the `setGaugeParameters` function ([reference](https://github.com/AngleProtocol/merkl-contracts/blob/32150c5577127a1feaf0315e1d7fcca0830eeb3c/contracts/partners/middleman/MerklGaugeMiddlemanTemplate.sol#L65) ). **3\. Automate Weekly (or Bi-weekly) Execution** Once your plugin is set up and your campaigns are correctly pre-formatted (a one-time setup), you only need to configure a mechanism within your voting contract to trigger execution automatically at your desired frequency. If you already have automation to push rewards to your other gauges, no additional setup is needed! [](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-dao#from-a-one-off-governance-proposal) From a One-Off Governance Proposal --------------------------------------------------------------------------------------------------------------------------------------------------------- Some protocols may need to execute one-off governance votes through onchain systems to deploy campaigns (typically for airdrops). To successfully deploy your campaign through onchain governance, you'll need to create a campaign payload, then use the [Foundry Forge CLI](https://book.getfoundry.sh/forge/) to generate the calldata for a DAO proposal. Follow these steps to build the payload and finalize your campaign creation. The example below is for the _Arbitrum network_. Be sure to select [the correct address](https://docs.merkl.xyz/integrate-merkl/smart-contract-addresses) for the Creator contract on your network. **1\. Create the Approval Transaction** Approve the Creator contract to spend tokens. Remember to include the Merkl fee in your calculation. Then use the output to craft the proposal action: **2\. Create the Accept Merkl Terms Transaction** Accept the Merkl Terms of Service: Example result: **3\. Copy and Edit the Payload** Follow the guides mentioned above to generate and copy the campaign payload. Here is the function selector for reference: Then update the format to be compatible with the Foundry CLI: * Replace square brackets `[` with parentheses `(`\ \ * Remove quotation marks `"`\ \ * Remove newlines\ \ * Add single quotes `'` around the entire payload\ \ \ For example:\ \ **4\. Create the** `**createCampaign**` **Transaction**\ \ Run the cast command using the properly formatted payload:\ \ The third and final transaction will look like this:\ \ [PreviousCreate a campaign from a multisig or Gnosis Safe](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-a-multisig-or-gnosis-safe)\ [NextCreate a point program](https://docs.merkl.xyz/distribute-with-merkl/create-a-point-program)\ \ Last updated 1 month ago\ \ * [Prerequisites](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-dao#prerequisites)\ \ * [From an Onchain Gauge System](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-dao#from-an-onchain-gauge-system)\ \ * [How It Works](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-dao#how-it-works)\ \ * [Step-by-Step Guide](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-dao#step-by-step-guide)\ \ * [From a One-Off Governance Proposal](https://docs.merkl.xyz/distribute-with-merkl/create-your-campaign-from-dao#from-a-one-off-governance-proposal)\ \ \ Copy\ \ cast calldata "approve(address,uint256)" 0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd 35175873467336683417086\ \ Copy\ \ {\ "target": "0x000D636bD52BFc1B3a699165Ef5aa340BEA8939c",\ "calldata": "0x095ea7b30000000000000000000000008bb4c975ff3c250e0ceea271728547f3802b36fd000000000000000000000000000000000000000000000772e34ed4c71327edfe"\ }\ \ Copy\ \ cast calldata "acceptConditions()"\ \ Copy\ \ {\ "target": "0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd",\ "calldata": "0x63b87bf0"\ }\ \ Copy\ \ createCampaign(\ tuple(\ bytes32, // campaignId\ address, // creator\ address, // rewardToken\ uint256, // amount\ uint32, // campaignType\ uint32, // startTimestamp\ uint32, // duration\ bytes, // campaignData\ ),\ )\ \ Copy\ \ ;[\ '0x0000000000000000000000000000000000000000000000000000000000000000',\ '0x0000000000000000000000000000000000000000',\ '0x000D636bD52BFc1B3a699165Ef5aa340BEA8939c',\ '35175873467336683417086',\ 4,\ 1734307200,\ 3600,\ '0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000005568747470733a2f2f616e676c652d626c6f672e696e667572612d697066732e696f2f697066732f516d5558667658666274526576376d377750796a464d4c736a777568457a676e796a334653376172714b69446f33000000000000000000000000000000000000000000000000000000000000000000000000000000000000194f70656e20446f6c6c617220626f6c74732072657761726473000000000000000000000000000000000000000000000000000000000000000000000000000000',\ ]\ \ Copy\ \ '(0x0000000000000000000000000000000000000000000000000000000000000000,0x0000000000000000000000000000000000000000,0x000D636bD52BFc1B3a699165Ef5aa340BEA8939c,35175873467336683417086,4,1734307200,3600,0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000000000000000000000000000000000000000000120000000000000000000000000000000000000000000000000000000000000005568747470733a2f2f616e676c652d626c6f672e696e667572612d697066732e696f2f697066732f516d5558667658666274526576376d377750796a464d4c736a777568457a676e796a334653376172714b69446f33000000000000000000000000000000000000000000000000000000000000000000000000000000000000194f70656e20446f6c6c617220626f6c74732072657761726473000000000000000000000000000000000000000000000000000000000000000000000000000000)'\ \ Copy\ \ cast calldata "createCampaign(tuple(bytes32,address,address,uint256,uint32,uint32,uint32,bytes))" '