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​