Creating a Campaign
This guide explains how to create reward campaigns using the Smart Rewarder platform.
Prerequisites
Before creating a campaign, ensure you have:
- Smart Rewarder SDK installed
- A whitelisted reward token (contact the Steer Protocol team for whitelisting)
- Sufficient reward token balance
- 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
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
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
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
Pre-creation Checks
- Verify reward token is whitelisted
- Check token allowance
- Validate campaign parameters
Transaction Monitoring
- Monitor approval transaction
- Monitor campaign creation transaction
- Implement proper error handling
IPFS Handling
- Store campaign metadata on IPFS
- Verify IPFS hash before using
- Keep metadata structure consistent
Next Steps
- Learn about Reward Claims
- Explore Campaign Management
- Set up monitoring and analytics