Skip to content

Token Distribution System

The token distribution system is a mechanism for managing token allocation and distribution. This tutorial will explain how to implement a secure and reliable token distribution system.

Features

  • Distribution Management
  • Batch Distribution
  • Locking Mechanism
  • Access Control
  • Emergency Handling

Contract Implementation

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "@openzeppelin/contracts/utils/math/SafeMath.sol";
import "@openzeppelin/contracts/security/Pausable.sol";

/**
 * @title TokenDistribution
 * @dev Token distribution contract implementation
 */
contract TokenDistribution is Ownable, ReentrancyGuard, Pausable {
    using SafeMath for uint256;

    // Distribution plan
    struct Distribution {
        uint256 amount;          // Distribution amount
        uint256 startTime;       // Start time
        uint256 duration;        // Duration
        uint256 interval;        // Release interval
        uint256 released;        // Released amount
        bool isActive;           // Whether active
    }

    // Recipient information
    struct Recipient {
        uint256 totalAmount;     // Total allocated amount
        uint256 releasedAmount;  // Released amount
        uint256 lastRelease;     // Last release time
        bool isActive;           // Whether active
    }

    // Configuration information
    struct DistributionConfig {
        uint256 minAmount;       // Minimum allocation
        uint256 maxAmount;       // Maximum allocation
        uint256 minDuration;     // Minimum period
        uint256 maxDuration;     // Maximum period
        bool requiresApproval;   // Whether approval required
        bool isActive;          // Whether active
    }

    // State variables
    IERC20 public token;                                     // Token contract
    mapping(bytes32 => Distribution) public distributions;    // Distribution plans
    mapping(bytes32 => mapping(address => Recipient)) public recipients;  // Recipient information
    mapping(address => bool) public operators;               // Operators
    DistributionConfig public config;                       // Configuration information

    // Events
    event DistributionCreated(bytes32 indexed id, uint256 amount, uint256 startTime, uint256 duration);
    event DistributionUpdated(bytes32 indexed id, bool isActive);
    event TokensDistributed(bytes32 indexed id, address indexed recipient, uint256 amount);
    event RecipientUpdated(bytes32 indexed id, address indexed recipient, uint256 amount, bool isActive);
    event OperatorUpdated(address indexed operator, bool status);
    event ConfigUpdated(uint256 minAmount, uint256 maxAmount, uint256 minDuration, uint256 maxDuration);

    /**
     * @dev Constructor
     */
    constructor(
        address _token,
        uint256 _minAmount,
        uint256 _maxAmount,
        uint256 _minDuration,
        uint256 _maxDuration
    ) {
        require(_token != address(0), "Invalid token");
        token = IERC20(_token);
        config = DistributionConfig({
            minAmount: _minAmount,
            maxAmount: _maxAmount,
            minDuration: _minDuration,
            maxDuration: _maxDuration,
            requiresApproval: true,
            isActive: true
        });
    }

    /**
     * @dev Create distribution plan
     */
    function createDistribution(
        uint256 _amount,
        uint256 _startTime,
        uint256 _duration,
        uint256 _interval
    ) external onlyOperator whenNotPaused returns (bytes32) {
        require(config.isActive, "Distribution not active");
        require(_amount >= config.minAmount && _amount <= config.maxAmount, "Invalid amount");
        require(_duration >= config.minDuration && _duration <= config.maxDuration, "Invalid duration");
        require(_interval > 0 && _interval <= _duration, "Invalid interval");
        require(_startTime >= block.timestamp, "Invalid start time");

        bytes32 id = keccak256(abi.encodePacked(
            block.timestamp,
            _amount,
            _startTime,
            _duration,
            _interval
        ));

        distributions[id] = Distribution({
            amount: _amount,
            startTime: _startTime,
            duration: _duration,
            interval: _interval,
            released: 0,
            isActive: true
        });

        emit DistributionCreated(id, _amount, _startTime, _duration);
        return id;
    }

    /**
     * @dev Add recipient
     */
    function addRecipient(
        bytes32 _id,
        address _recipient,
        uint256 _amount
    ) external onlyOperator {
        require(_recipient != address(0), "Invalid recipient");
        Distribution storage dist = distributions[_id];
        require(dist.isActive, "Distribution not active");
        require(dist.released.add(_amount) <= dist.amount, "Exceeds distribution amount");

        recipients[_id][_recipient] = Recipient({
            totalAmount: _amount,
            releasedAmount: 0,
            lastRelease: 0,
            isActive: true
        });

        emit RecipientUpdated(_id, _recipient, _amount, true);
    }

    /**
     * @dev Batch add recipients
     */
    function addRecipients(
        bytes32 _id,
        address[] calldata _recipients,
        uint256[] calldata _amounts
    ) external onlyOperator {
        require(_recipients.length == _amounts.length, "Length mismatch");
        Distribution storage dist = distributions[_id];
        require(dist.isActive, "Distribution not active");

        uint256 totalAmount = 0;
        for (uint256 i = 0; i < _amounts.length; i++) {
            totalAmount = totalAmount.add(_amounts[i]);
        }
        require(dist.released.add(totalAmount) <= dist.amount, "Exceeds distribution amount");

        for (uint256 i = 0; i < _recipients.length; i++) {
            address recipient = _recipients[i];
            uint256 amount = _amounts[i];
            require(recipient != address(0), "Invalid recipient");

            recipients[_id][recipient] = Recipient({
                totalAmount: amount,
                releasedAmount: 0,
                lastRelease: 0,
                isActive: true
            });

            emit RecipientUpdated(_id, recipient, amount, true);
        }
    }

    /**
     * @dev Release tokens
     */
    function release(
        bytes32 _id,
        address _recipient
    ) external nonReentrant whenNotPaused returns (uint256) {
        Distribution storage dist = distributions[_id];
        require(dist.isActive, "Distribution not active");
        require(block.timestamp >= dist.startTime, "Not started");

        Recipient storage recipient = recipients[_id][_recipient];
        require(recipient.isActive, "Recipient not active");

        uint256 releasable = getReleasableAmount(_id, _recipient);
        require(releasable > 0, "No tokens to release");

        recipient.releasedAmount = recipient.releasedAmount.add(releasable);
        recipient.lastRelease = block.timestamp;
        dist.released = dist.released.add(releasable);

        require(
            token.transfer(_recipient, releasable),
            "Transfer failed"
        );

        emit TokensDistributed(_id, _recipient, releasable);
        return releasable;
    }

    /**
     * @dev Batch release tokens
     */
    function batchRelease(
        bytes32 _id,
        address[] calldata _recipients
    ) external nonReentrant whenNotPaused returns (uint256) {
        uint256 totalReleased = 0;
        for (uint256 i = 0; i < _recipients.length; i++) {
            uint256 released = release(_id, _recipients[i]);
            totalReleased = totalReleased.add(released);
        }
        return totalReleased;
    }

    /**
     * @dev Calculate releasable amount
     */
    function getReleasableAmount(
        bytes32 _id,
        address _recipient
    ) public view returns (uint256) {
        Distribution storage dist = distributions[_id];
        Recipient storage recipient = recipients[_id][_recipient];

        if (!dist.isActive || !recipient.isActive || block.timestamp < dist.startTime) {
            return 0;
        }

        uint256 elapsedTime = block.timestamp.sub(dist.startTime);
        if (elapsedTime > dist.duration) {
            return recipient.totalAmount.sub(recipient.releasedAmount);
        }

        uint256 intervals = elapsedTime.div(dist.interval);
        uint256 releasable = recipient.totalAmount.mul(intervals).div(dist.duration.div(dist.interval));
        return releasable.sub(recipient.releasedAmount);
    }
}

System Architecture

1. Core Components

  • Distribution Contract: Manages token distribution
  • Plan Management: Controls distribution plans
  • Recipient System: Manages recipients
  • Release Module: Handles token releases

2. Process Flow

  1. Create distribution plan
  2. Add recipients
  3. Calculate releases
  4. Execute distributions
  5. Track progress

Security Measures

1. Access Control

  • Operator permissions
  • Plan management
  • Release controls
  • Emergency pause

2. Distribution Security

  • Amount validation
  • Timing controls
  • Release tracking
  • Balance checks

Best Practices

1. Implementation Guidelines

  • Validate all inputs
  • Implement proper access control
  • Handle edge cases
  • Maintain comprehensive logs

2. Operation Guidelines

  • Regular security audits
  • Plan management
  • Emergency response plan
  • Regular status reviews

FAQ

1. Basic Concepts

Q: What is token distribution? A: Token distribution is a mechanism for allocating and releasing tokens to multiple recipients according to predefined schedules and rules.

Q: How does distribution scheduling work? A: Distribution scheduling involves:

  • Plan creation
  • Timing control
  • Release calculation
  • Progress tracking

2. Security

Q: How to ensure distribution security? A: Security measures include:

  • Access control
  • Amount validation
  • Release verification
  • Emergency mechanisms
  • Regular audits

Q: How to handle distribution attacks? A: Protection measures include:

  • Input validation
  • Rate limiting
  • Balance checks
  • Status monitoring
  • Quick response plan

3. Operations

Q: How to manage distributions effectively? A: Management strategies include:

  • Plan organization
  • Recipient management
  • Release scheduling
  • Progress monitoring
  • Documentation

Q: How to handle distribution issues? A: Issue resolution includes:

  • Error checking
  • Status verification
  • Balance reconciliation
  • Support system
  • Clear communication

4. Maintenance

Q: How to maintain the distribution system? A: Maintenance includes:

  • Regular updates
  • Performance monitoring
  • Security checks
  • Plan reviews
  • Documentation updates

Q: How to monitor distribution progress? A: Monitoring includes:

  • Release tracking
  • Balance checking
  • Status updates
  • Error logging
  • Success metrics

Released under the MIT License by Vogeb.