SHiNE-server/Dev_Docs/Pending_Features/2026-06-11_pda-anti-griefing-create.md
AidarKC cf6a2830c8 solana: закрыть griefing создания PDA и заморозку выплат, добавить аудит №2
shine_payments + shine_users:
- create_pda_account переведён на «создание поверх предзаполненного»
  (allocate+assign+добор ренты), чтобы подсев лампортов на детерминированный
  адрес PDA (тикет/логин) не блокировал создание — закрыт LOW из аудита №1;
  в shine_payments is_uninitialized_account перестала зависеть от баланса.

shine_payments (HIGH из аудита №2):
- запрещён recipient == inflow_vault в buy_ticket*, manager_add_ticket и
  change_ticket_recipient; добавлена защита по умолчанию в transfer_from_vault
  (require vault.key != recipient.key). Это убирает алиасинг аккаунта в
  step_payout, который навсегда замораживал очередь выплат и средства вольта.

Документация и учёт:
- doc/programs/shine_payments.md §3.4, §10.1; doc/programs/shine_users.md §3.3;
- Dev_Docs/audit: добавлен аудит №2, обе закрытые находки помечены ИСПРАВЛЕНО;
- Dev_Docs/Pending_Features: две записи на ручную e2e-проверку на devnet;
- VERSION.properties: client 1.2.161, server 1.2.150.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-11 04:10:31 +04:00

2.6 KiB
Raw Blame History

Устойчивое создание PDA (защита от «минирования» адреса)

Краткое описание

В shine_payments и shine_users функция create_pda_account переведена с жёсткого system_instruction::create_account на паттерн «создание поверх предзаполненного»:

  • если на детерминированном адресе будущего PDA нет лампортов — обычный create_account;
  • если лампорты уже есть («подсев» атакующим) — добор ренты переводом, затем allocate + assign под подписью PDA.

Дополнительно в shine_payments is_uninitialized_account перестала требовать нулевой баланс (проверяет только пустые данные + владельца System Program).

Это закрывает последний (LOW) пункт аудита: griefing-DoS на покупку тикетов и сквоттинг логинов через предсказуемые адреса PDA.

Что проверять (devnet/localnet)

  1. Обычная покупка тикета без «подсева» — создаётся как раньше (быстрый путь).
  2. На адрес следующего тикета заранее переведены лампорты обычным system-переводом → покупка/manager_add_ticket всё равно проходит, тикет создаётся корректно, данные и владелец = program id.
  3. На адрес user_pda будущего логина заранее переведены лампорты → регистрация логина (create_user_pda) всё равно проходит; запись и комиссия корректны.
  4. Повторная инициализация уже существующего тикета/пользователя по-прежнему отклоняется (PdaAlreadyExists / UserAlreadyExists).
  5. Singleton-PDA (init, economy config) и manager allowance создаются без регрессий.

Ожидаемый результат

Подсев лампортов на заранее известный адрес PDA не блокирует создание; вся остальная экономика и проверки повторной инициализации работают как прежде.

Статус

pending