Skip to content

Константы и переменные состояния #4

@myltik1702

Description

@myltik1702

Разберём представленный фрагмент смарт‑контракта детально — с пояснением логики, потенциальных рисков и вариантов оптимизации.


1. Константы и переменные состояния

uint256 public constant MAX_SUPPLY = 1_000_000_000 * 10**18; // 1 млрд токенов
uint8 private _decimals = 18;

Что делает:

  • MAX_SUPPLY — максимальная эмиссия: 1 млрд токенов с 18 знаками после запятой (как ETH).
  • _decimals — количество десятичных знаков (стандарт для ERC‑20).

Риски/замечания:

  • Опечатка в имени константы: MAX_SUPPLY → должно быть MAX_SUPPLY (но лучше MAX_SUPPLY или TOTAL_SUPPLY).
  • Жёсткая привязка к 18 десятичным знакам ограничивает гибкость (но это стандарт).

2. Управление комиссиями

mapping(address => bool) public exemptFromFees;
uint16 public feeRate = 500; // 5%

Что делает:

  • exemptFromFees — список адресов, не платящих комиссию.
  • feeRate — ставка комиссии в базисных пунктах (500 = 5 %).

Риски/замечания:

  • uint16 ограничивает ставку до 655,35 % (достаточно для большинства сценариев).
  • Публичный статус exemptFromFees позволяет любому читать список исключений (это нормально).

3. Конструктор

constructor() ERC20("Starflow of Abundance", "SFA") {
    _mint(msg.sender, MAX_SUPPLY);
    exemptFromFees[msg.sender] = true;
}

Что делает:

  • Инициализирует токен с именем и символом.
  • Выпускает все токены на адрес создателя.
  • Добавляет создателя в список исключённых от комиссий.

Риски/замечания:

  • Вся эмиссия у одного адреса — риск централизации.
  • Нет механизмов распределения (стейкинг, продажи и т. п.).

4. Функции управления

setFeeRate

function setFeeRate(uint16 newRate) public onlyOwner {
    require(newRate <= 10000, "Fee rate cannot exceed 100%");
    feeRate = newRate;
}

Что делает: Позволяет владельцу изменить ставку комиссии (максимум 100 %).

Оптимизация:

  • Добавить событие emit FeeRateChanged(newRate) для отслеживания.

setExemptFromFees

function setExemptFromFees(address account, bool exempt) public onlyOwner {
    exemptFromFees[account] = exempt;
}

Что делает: Добавляет/удаляет адреса из списка исключений.

Оптимизация:

  • Добавить проверку require(account != address(0)).

5. Логика переводов с комиссией

transfer

function transfer(address recipient, uint256 amount) public override whenNotPaused returns (bool) {
    uint256 fee = 0;
    if (!exemptFromFees[msg.sender]) {
        fee = amount.mul(feeRate).div(10000);
        amount = amount.sub(fee);
        _transfer(msg.sender, address(this), fee); // Комиссия в казначейство
    }
    _transfer(msg.sender, recipient, amount);
    return true;
}

Что делает:

  1. Проверяет, платит ли отправитель комиссию.
  2. Рассчитывает комиссию: amount * feeRate / 10 000.
  3. Переводит комиссию на контракт (казначейство).
  4. Переводит остаток получателю.

Риски/замечания:

  • Использование SafeMath (.mul, .div, .sub) защищает от переполнения.
  • Комиссия идёт на адрес контракта — нужно добавить функцию вывода.
  • Нет проверки на нулевой адрес получателя.

transferFrom

Аналогична transfer, но работает через одобрение (allowance).

Оптимизация:

  • Объединить логику комиссии в отдельную функцию-модификатор.

6. Дополнительные функции

burn

function burn(uint256 amount) public onlyOwner {
    _burn(msg.sender, amount);
}

Что делает: Сжигает токены с адреса владельца.

Риски/замечания:

  • Только владелец может сжигать — централизация.
  • Нет механизма децентрализованного сжигания.

emergencyWithdraw

function emergencyWithdraw(address to, uint256 amount) public onlyOwner {
    _transfer(msg.sender, to, amount);
}

Что делает: Переводит токены без комиссии (экстренная ситуация).

Риски/замечания:

  • Риск злоупотребления со стороны владельца.
  • Нет лимитов на сумму.

pause / unpause

function pause() public onlyOwner { _pause(); }
function unpause() public onlyOwner { _unpause(); }

Что делает: Приостанавливает/возобновляет все переводы.

Оптимизация:

  • Добавить события Paused и Unpaused.

Рекомендации по улучшению

  1. Добавить события (events)

    event FeeRateChanged(uint16 newRate);
    event ExemptionUpdated(address account, bool exempt);
    event Paused();
    event Unpaused();
  2. Функция вывода комиссий

    function withdrawFees(address payable to) public onlyOwner {
        uint256 balance = balanceOf(address(this));
        _transfer(address(this), to, balance);
    }
  3. Проверка нулевых адресов

    require(recipient != address(0), "ERC20: transfer to zero address");
  4. Ограничение на emergencyWithdraw
    Добавить дневной лимит или мультисиг.

  5. Документация Natspec
    Дополнить комментарии для автогенерации документации.

  6. Тестирование

    • Проверить крайние случаи (максимальная комиссия, нулевые переводы).
    • Протестировать паузу/возобновление.
  7. Безопасность

    • Провести аудит с помощью Slither, MythX.
    • Добавить receive()/fallback для ETH.

Итоговый вывод

Код реализует базовую версию токена с комиссией и управлением, но требует:

  • Доработки безопасности.
  • Добавления механизмов децентрализации.
  • Юридической проверки (KYC/AML, регуляторные риски).
  • Тестирования в тестовых сетях.

Для продакшена обязательно провести:

  1. Внешний аудит смарт‑контракта.
  2. Юридическое согласование.
  3. Бета‑тестирование с ограниченной эмиссией.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions