Skip to main content

Creating a Campaign

This guide explains how to create reward campaigns using the Smart Rewarder platform.

Prerequisites

Before creating a campaign, ensure you have:

  1. Smart Rewarder SDK installed
  2. A whitelisted reward token (contact the Steer Protocol team for whitelisting)
  3. Sufficient reward token balance
  4. Access to IPFS for campaign metadata

Implementation Steps

1. Get Smart Rewarder Contract

First, fetch the Smart Rewarder contract address for your chain:

const contracts = await smartRewards.getSmartRewarderContracts();
const contract = contracts.data?.find(c => c.chainId === chainId);

if (!contract) {
throw new Error(`No Smart Rewarder contract found for chain ${chainId}`);
}

2. Prepare Campaign Parameters

Create your campaign configuration:

// Campaign metadata to be stored on IPFS
const campaignMetadata = {
execution_bundle: "QmepJYrV2jSAL7eWhEUgE8rRBHQWg4uFmNGJBfC1Gb15xv",
execution_parameters: {
tokenAddress: "0x1ab39c875e00ef63758c571c3f6292c3d94ddd28"
},
description: "Increase liquidity in a specific vault to improve market depth and reduce slippage.",
name: "Boost liquidity",
protocol: "Uniswap",
category: "Liquidity Boost",
epochLength: 21600,
campaignType: "token_balance_rewards"
};

// Upload to IPFS and get hash
const ipfsHash = await uploadToIPFS(campaignMetadata);

3. Create Campaign

Using Viem

import { parseEther } from 'viem';

// Get current block for timing calculations
const currentBlock = await publicClient.getBlockNumber();
const blocksPerDay = 332308;
const blocksPerYear = blocksPerDay * 365;

const campaignParams = {
owner: address, // Your wallet address
liquidityPool: poolAddress,
rewardToken: rewardTokenAddress,
escrowAmount: parseEther('25'),
startBlock: currentBlock + 550, // Start after ~2 hours
endBlock: currentBlock + blocksPerYear,
campaignParamsIPFSHash: ipfsHash
};

// First approve reward token spending
const erc20Contract = {
address: rewardTokenAddress,
abi: [{
name: 'approve',
type: 'function',
inputs: [
{ name: 'spender', type: 'address' },
{ name: 'amount', type: 'uint256' }
],
outputs: [{ type: 'bool' }]
}]
};

await walletClient.writeContract({
...erc20Contract,
functionName: 'approve',
args: [contract.address, campaignParams.escrowAmount]
});

// Create campaign
const smartRewardContract = {
address: contract.address,
abi: [{
name: 'createRewardCampaign',
type: 'function',
inputs: [{
components: [
{ name: 'owner', type: 'address' },
{ name: 'liquidityPool', type: 'address' },
{ name: 'rewardToken', type: 'address' },
{ name: 'escrowAmount', type: 'uint256' },
{ name: 'startBlock', type: 'uint256' },
{ name: 'endBlock', type: 'uint256' },
{ name: 'campaignParamsIPFSHash', type: 'string' }
],
name: 'newRewardCampaign',
type: 'tuple'
}],
outputs: [{ type: 'uint256' }]
}]
};

const hash = await walletClient.writeContract({
...smartRewardContract,
functionName: 'createRewardCampaign',
args: [campaignParams]
});

Using Ethers.js

import { ethers } from 'ethers';

const smartRewardContract = new ethers.Contract(
contract.address,
smartRewardABI,
signer
);

// Approve token spending
const erc20Contract = new ethers.Contract(
rewardTokenAddress,
erc20ABI,
signer
);

await erc20Contract.approve(
contract.address,
ethers.utils.parseEther('25')
);

// Create campaign
const tx = await smartRewardContract.createRewardCampaign(campaignParams);
await tx.wait();

Important Notes

  1. Reward Token Whitelisting

    • Only whitelisted tokens can be used as reward tokens
    • Contact the Steer Protocol team to whitelist your token
    • Check if token is whitelisted before creating campaign
  2. Campaign Timing

    • Start block should be in the future (recommended: current block + 550)
    • End block calculation: currentBlock + (blocksPerDay * days)
    • Consider block time variations on different chains
  3. Gas Optimization

    • Implement proper gas estimation
    • Add buffer to gas estimates (e.g., multiply by 1.2)
    • Consider network congestion

Error Handling

try {
// Check if token is whitelisted
const rewardAmounts = await smartRewardContract.minimumRewardTokenAmounts(
rewardTokenAddress
);

// If token not whitelisted, this will throw
if (rewardAmounts.eq(0)) {
throw new Error('Reward token not whitelisted');
}

// Proceed with campaign creation
// ...
} catch (error) {
console.error('Campaign creation failed:', error);
// Handle error appropriately
}

Best Practices

  1. Pre-creation Checks

    • Verify reward token is whitelisted
    • Check token allowance
    • Validate campaign parameters
  2. Transaction Monitoring

    • Monitor approval transaction
    • Monitor campaign creation transaction
    • Implement proper error handling
  3. IPFS Handling

    • Store campaign metadata on IPFS
    • Verify IPFS hash before using
    • Keep metadata structure consistent

Next Steps