Automating campaigns
Automate recurring or gauge-driven Merkl campaigns by deploying a middleman contract that bakes in the configuration and only takes the amount each cycle
The previous pages create a single campaign by hand — building a configuration, encoding it, and signing the transactions. If instead you run recurring campaigns — weekly liquidity incentives, biweekly emissions, monthly rewards — or want an onchain gauge to launch them, you don't want a human (or a multisig) repeating those steps every cycle. The clean pattern is to deploy a middleman smart contract that bakes the configuration in once and exposes a single function to launch the next campaign with an amount.
From then on, your weekly operation is reduced to two steps:
- Transfer the reward tokens to the middleman.
- Have a bot call the middleman with the amount.
The middleman handles the approval, calls Merkl's DistributionCreator, and creates the campaign with the pre-set rules. No multisig signing, no parameter drift between cycles, no human in the loop, and no risk that the wrong campaign config gets pushed.
Recommended template
We recommend using the StandardMiddleman contract:
It's audited (alongside the rest of the Merkl contracts) and supports the full set of Merkl campaign features.
How it works
The contract holds three pieces of state:
defaultParams— the fullCampaignParametersstruct used for every campaign created through it (campaign type, target pool, duration, hooks, blacklist/whitelist, etc.).executors— an allowlist of addresses authorized to trigger campaign creation (e.g. your bot's hot wallet, or your gauge contract).startTimestampOffset— how far in the past the campaign should start, useful for retroactive distributions.
The runtime entrypoint is a single function:
function notifyReward(uint256 amount) external;
When called by an authorized executor, it:
- Verifies the caller is in
executors. - Approves the
DistributionCreatorforamountof the reward token (idempotent — handled internally). - Calls
DistributionCreator.createCampaign(params)withdefaultParams, the suppliedamount, andblock.timestamp - startTimestampOffsetas the start time.
That's it. The campaign launches with the exact parameters baked in at deployment.
One-time setup
Performed by the contract owner:
- Deploy
StandardMiddlemanwith the MerklDistributionCreatoraddress. - Configure the campaign template via
setDefaultParameters(...)— this is where you bake in the pool, the duration, the customization hooks, and any other Merkl options for your recurring campaigns. - Whitelist the bot wallet (or the calling contract) via
setExecutor(...).
After this, the contract is ready. The owner can update parameters or rotate executors at any time, and recoverToken(...) is available as an emergency escape hatch.
Recurring operation
Every cycle (e.g. each Monday):
- Transfer the cycle's reward budget to the middleman.
- Bot calls
notifyReward(amount).
A new Merkl campaign is created with the hardcoded rules and the amount you just funded. Nothing else changes between cycles unless the owner explicitly updates the parameters.
Building the parameters
The defaultParams you bake into the middleman is the same CampaignParameters you'd build for any campaign — exactly what Understanding campaign configs, Creating the payloads, and Transactions to sign walk through.
The easiest way to get the right values is to:
- Build the configuration for your recurring campaign — in Merkl Studio (see the campaign creation guide) or programmatically (see Creating the payloads).
- Copy the struct fields Studio produces for its multisig flow — they map directly to what you pass to
setDefaultParameters(...). TheCampaignParametersreference lists each field.
Use cases
Recurring institutional emissions
A foundation, treasury, or protocol DAO that pays out weekly liquidity incentives can deploy one middleman per pool (or one shared middleman with a more advanced parameter mapping) and cut the operational burden to "send tokens, run bot." Every campaign is verifiably identical to the previous one — auditable, reproducible, no human discretion required.
Onchain gauge systems
Many protocols rely on gauge systems where users vote onchain to determine reward allocations. The middleman pattern slots in naturally: the gauge calls the middleman's notifyReward(amount) function (the standard interface gauge systems already use), and the middleman creates the corresponding Merkl campaign.
This combines Merkl's flexibility (campaign types, hooks, customization options, reporting) with the trustlessness of a fully onchain emission flow.
Several teams have shipped variations of this pattern:
If your gauge system calls a different function signature than notifyReward(uint256), you'll want a thin wrapper or a forked middleman with the matching interface — the rest of the logic stays the same.
Need help?
If your setup needs custom parameter logic (per-pool allocation, dynamic durations, multiple reward tokens), reach out to the Merkl team — we can help you adapt the template or design a fit-for-purpose middleman.
