Voting System for Fan Token Holders Development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Voting System for Fan Token Holders Development
Medium
~3-5 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Fan Token Holder Voting System Development

Fan tokens are special governance tokens. Chiliz, Socios, Rally — markets where sports clubs and cultural figures issue tokens and give holders voting rights on decisions: kit design, stadium songs, food menus. This is engagement mechanics, not financial governance — architecture differs fundamentally from protocol DAOs.

Core requirements: high throughput (thousands of votes in hours), simple UX (fans aren't crypto-native), manipulation protection (one whale can't overpower community), result transparency.

Architecture: On-chain vs Off-chain vs Hybrid

Pure on-chain doesn't work: gas costs deter mass audience; network latency creates delays; polls like "which color for new sneakers" don't need blockchain for every vote.

Recommended: hybrid approach:

  • Token balance snapshot taken on-chain (specific block = specific moment)
  • Votes themselves — off-chain signatures (like Snapshot Protocol)
  • Aggregated results and proof of correct counting published on-chain
contract FanTokenVoting {
    struct Poll {
        uint256 id;
        string title;
        string[] choices;
        uint256 snapshotBlock;      // block for balance snapshot
        uint256 startTime;
        uint256 endTime;
        uint256 minTokenBalance;    // minimum balance to participate
        PollStatus status;
        bytes32 resultsHash;        // hash of results after closing
    }
    
    enum PollStatus { Draft, Active, Closed, ResultsPublished }
    
    IERC20 public immutable fanToken;
    address public operator;        // club/team
    
    mapping(uint256 => Poll) public polls;
    mapping(uint256 => mapping(uint256 => uint256)) public pollResults;
    uint256 public pollCount;
    
    event PollCreated(uint256 indexed pollId, string title, uint256 snapshotBlock);
    event ResultsPublished(uint256 indexed pollId, bytes32 resultsHash, uint256[] voteCounts);
    
    function createPoll(
        string calldata title,
        string[] calldata choices,
        uint256 durationSeconds,
        uint256 minTokenBalance
    ) external onlyOperator returns (uint256 pollId) {
        require(choices.length >= 2 && choices.length <= 10, "Invalid choices");
        
        pollId = ++pollCount;
        polls[pollId] = Poll({
            id: pollId,
            title: title,
            choices: choices,
            snapshotBlock: block.number,
            startTime: block.timestamp,
            endTime: block.timestamp + durationSeconds,
            minTokenBalance: minTokenBalance,
            status: PollStatus.Active,
            resultsHash: bytes32(0)
        });
        
        emit PollCreated(pollId, title, block.number);
    }
}

Off-chain Vote Aggregation Service

Off-chain service verifies each vote signature, checks snapshot balance, and aggregates results.

class VoteAggregator {
    constructor(provider, fanTokenAddress) {
        this.provider = provider;
        this.fanToken = new ethers.Contract(
            fanTokenAddress,
            ['function balanceOf(address) view returns (uint256)'],
            provider
        );
    }
    
    async processVote(vote, poll) {
        // 1. Verify signature
        const messageHash = ethers.solidityPackedKeccak256(
            ['uint256', 'uint256', 'address'],
            [vote.pollId, vote.choiceIndex, vote.voter]
        );
        const recoveredAddress = ethers.verifyMessage(
            ethers.getBytes(messageHash),
            vote.signature
        );
        
        if (recoveredAddress.toLowerCase() !== vote.voter.toLowerCase()) {
            throw new Error('Invalid signature');
        }
        
        // 2. Check balance at snapshot block
        const balance = await this.fanToken.balanceOf(
            vote.voter,
            { blockTag: poll.snapshotBlock }
        );
        
        if (balance < poll.minTokenBalance) {
            throw new Error('Insufficient balance');
        }
        
        // 3. Check time window
        if (vote.timestamp < poll.startTime || vote.timestamp > poll.endTime) {
            throw new Error('Vote outside poll period');
        }
        
        return {
            voter: vote.voter,
            choice: vote.choiceIndex,
            votingPower: balance
        };
    }
}

Whale Protection

When one holder has 30–40% supply, standard "1 token = 1 vote" becomes dictatorship. One speculative whale overpowers thousands of real fans.

Quadratic Voting: voting power = √(balance). 10,000 tokens give weight 100, not 10,000. Effectively reduces whale power.

Capping: maximum vote weight is capped (e.g., 1% of total votes). Simple but crude.

Time-weighted balance: counts average balance over 30 days, not current. Prevents pre-vote token buying.

Mechanism Complexity Whale Protection UX Complexity
1 token = 1 vote Low None None
Quadratic voting Medium High Medium
Balance capping Low Medium None
Time-weighted Medium Medium None

UX for Mass Audience

Fans don't understand Web3. Simplicity priority:

Gasless voting: votes via signatures without gas payment. Operator covers via meta-transactions (ERC-2771, Biconomy).

Social login: Magic.link or Privy — wallet auto-created on Google/Apple login. Fan doesn't know they have wallet.

Notifications: push notifications about new polls and results via Firebase + mobile app. Snapshot.org as backup for crypto-native users.

Transparency without complexity: results shown as simple chart. On-chain verification link available but not prominent.

Development Timeline

Backend (vote aggregation, API) + smart contract + integration: 6–8 weeks. Full platform with mobile app, social login, notifications, analytics: 4–5 months.