Skip to Content
⚔ BattleMeme docs · early preview · expect rough edges
PlayUse vouchers

Use vouchers

How to create a voucher campaign as a token creator, and how to redeem one as a recipient.

Vouchers are an off-chain-distributed, on-chain-redeemed promo primitive. Pre-fund ETH, hand out tickets, let recipients self-redeem. See Vouchers (protocol) for the mechanism.

Create a campaign — creator side

Open /voucher/new. You’ll choose between Link mode (open-link / QR distribution) and Whitelist mode (Merkle-gated wallets).

Step 1 — Pick a mode

🔗 Open link — sign N vouchers; share each as a link. Anyone with the link can claim — first wallet wins. Good for:

  • Public airdrop drops where you don’t know recipients in advance
  • KOL marketing where you DM each influencer a unique URL
  • Drops that feel like “scratch tickets”

📋 Whitelist — restrict to specific wallets, each redeems up to their declared allocation. Good for:

  • Pre-announced allowlist (followers, partners)
  • Anti-bot drops (no public link to scrape)
  • Per-wallet quotas (give one wallet 1 voucher, another 10)

Step 2 — Pick a token

Use the token search. The list is filtered to INIT / BATTLE / GRADUATED tokens only — frozen states won’t accept vouchers.

Step 3 — Voucher amount (ETH per voucher)

The fixed ETH that each voucher will spend at redeem time. Minimum 0.001 ETH. The contract enforces this — going lower reverts with BadEthPerVoucher.

Common presets: 0.01, 0.05, 0.1, 0.5 ETH.

Step 4 — Distribution-specific config

Link mode:

  • Set Total vouchers (1 to 1000). Each voucher is one redeemable slot.
  • msg.value you’ll pay = ethPerVoucher × totalVouchers. UI computes & shows.

Whitelist mode:

  • Paste or upload addresses (one per line, comments start with #).
  • Each wallet listed will get 1 voucher by default; if you want per-wallet allocations > 1, edit the textarea: 0xABC… 5 (address, space, allocation).
  • The UI builds the Merkle tree client-side, computes the root, and submits it with the campaign.
  • msg.value = ethPerVoucher × sum(all allocations).

Step 5 — Sign & send

UI calls VoucherManager.createCampaign(...) (Link) or createCampaignWhitelist(...) (Whitelist) with the ETH attached. Confirm in your wallet.

After confirmation:

  • Link mode: UI prompts you to sign N vouchers (one eth_personal_sign per slot). The signatures are persisted locally + optionally posted to the protocol’s signing-service for short-code lookup. UI then opens the QR / link sharing modal — one link per voucher slot.
  • Whitelist mode: UI persists the Merkle tree locally + posts to signing-service. Recipients fetch their proof from that store at redeem time.

Step 6 — Share

Link mode outputs:

https://battle.meme/voucher/redeem?c=42&v=7&s=0xabc…

Or a short-code wrapped via the signing-service:

https://battle.meme/voucher/redeem?code=8h2k9p

Drop in DMs, Telegram, X DMs, QR posters, etc. The first wallet to redeem each slot wins (one wallet can claim at most one slot per campaign).

Whitelist mode outputs:

https://battle.meme/voucher/redeem?c=42

Send to your whitelisted wallets. The UI auto-resolves their allocation + Merkle proof from the persisted tree.

Cancel a campaign

Open /voucher/dashboard (or your portfolio).

  • Cancel specific slots — pick voucher indexes that haven’t been redeemed yet; refund returns to you. Already-redeemed slots are silently skipped.
  • Cancel all — fast-path. Marks the campaign cancelled (subsequent redeems short-circuit) and refunds every un-redeemed slot in one tx.

Redeem a voucher — recipient side

Open the link the creator sent you. The redeem page (/voucher/redeem?…) decodes the params from the URL.

  1. Connect wallet.
  2. UI shows: token, ETH per voucher, expected token output (preview based on current pool price), creator address, slippage tolerance.
  3. Click Redeem voucher.
  4. UI calls VoucherManager.redeem(campaignId, voucherIndex, signature, minTokensOut).
  5. The contract:
    • Verifies signature recovers to campaign.signer
    • Marks this slot consumed forever
    • Marks your wallet “claimed in this campaign” (you can’t claim another slot in the same Link campaign)
    • Swaps ethPerVoucher ETH → TOKEN at current pool price
    • Forwards the TOKEN output to your wallet

Common errors:

ErrorCauseFix
AlreadyRedeemedSlot was claimed by someone else firstSorry, first wallet wins
AlreadyClaimedInCampaignYou already redeemed a different slot in this campaignOne per wallet per campaign
BadSignatureSignature mismatch (corrupted link?)Get a fresh link from the creator
BadTokenStateToken entered a frozen state (QUEUE / WARMUP / ELIMINATED / LOST)Wait for INIT/BATTLE/GRADUATED
SlippageTooHighPool moved; would give fewer tokens than minTokensOutIncrease slippage tolerance in UI and retry

Whitelist mode — recipient flow

  1. Connect wallet — the wallet must be in the whitelist.
  2. UI fetches the tree (from signing-service or local cache) and computes your Merkle proof + allocation.
  3. UI shows: token, ETH per voucher, your allocation, how many you’ve already redeemed.
  4. Click Redeem voucher (you can redeem multiple times up to your allocation).
  5. UI calls VoucherManager.redeemWhitelist(campaignId, allocation, proof, minTokensOut).
  6. The contract:
    • Verifies keccak(keccak(abi.encode(msg.sender, allocation))) is in the tree (via proof)
    • Increments whitelistRedeemedBy[campaignId][msg.sender]
    • Reverts OverAllocation if count would exceed allocation
    • Swaps ethPerVoucher ETH → TOKEN
    • Forwards the TOKEN output to your wallet

Common errors:

ErrorCauseFix
BadProofWallet isn’t in the whitelist, or proof is wrongYou’re not on the list — DM the creator
OverAllocationAlready redeemed your full allocationAll used up
BadTokenStateToken entered a frozen stateWait
SlippageTooHighPool movedRaise slippage

Receive-side outcome

After a successful redeem, your wallet holds the token. Same as if you’d manually swapped ethPerVoucher ETH on Uniswap — except the creator paid the ETH.

Now you can:

  • Hold the token through the battle (if it’s still pre-graduation)
  • Sell on Uniswap any time (subject to state-machine gates)
  • Use it to qualify for further drops, etc.

Gas + fee notes

  • Recipient pays gas for the redeem tx.
  • The 1.3% pool fee still applies on the underlying swap — split as normal (1.0% LP fee + 0.3% creator). Yes, the campaign creator is paying for a swap that ALSO earns them 0.3% of the swap — slightly comical but matches every other buy.
  • No additional protocol fee on top of the swap fee.

See also: Vouchers (mechanism), VoucherManager contract.