SHA256
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>
This commit is contained in:
co-authored by
Claude Fable 5
parent
01d9553db4
commit
cf6a2830c8
@@ -0,0 +1,33 @@
|
||||
# Запрет получателя тикета, равного inflow-вольту (защита от заморозки очереди)
|
||||
|
||||
## Краткое описание
|
||||
Закрыта HIGH-находка второго аудита (`Dev_Docs/audit/Solana-audit-2-by-Claude-11июня2026.md`).
|
||||
Тикет с `recipient_wallet == адрес inflow_vault` приводил к алиасингу аккаунта в
|
||||
`step_payout` (вольт одновременно источник и получатель), второй mutable-займ
|
||||
лампортов в `transfer_from_vault` падал, и такой тикет навсегда блокировал
|
||||
обслуживание очереди и замораживал средства вольта.
|
||||
|
||||
Исправление в `shine_payments`:
|
||||
- `buy_ticket_by_purchase_usd` — `require!(recipient_wallet != config.inflow_vault)`;
|
||||
- `process_manager_add_ticket` — запрет через `find_single_pda(INFLOW_VAULT_SEED)`;
|
||||
- `process_change_ticket_recipient` — тот же запрет для `new_recipient_wallet`;
|
||||
- `transfer_from_vault` — защита по умолчанию `require!(vault.key != recipient.key)`.
|
||||
|
||||
Ошибка во всех случаях — `InvalidTicketRecipient`.
|
||||
|
||||
## Что проверять (devnet/localnet)
|
||||
1. Покупка тикета с `recipient_wallet = <адрес inflow_vault PDA>` → отклоняется
|
||||
(`InvalidTicketRecipient`), тикет не создаётся.
|
||||
2. `manager_add_ticket` с тем же recipient → отклоняется.
|
||||
3. `change_ticket_recipient` с `new_recipient = inflow_vault` → отклоняется.
|
||||
4. Обычные покупки/выплаты с нормальным получателем → работают как раньше, очередь
|
||||
обслуживается, `step_payout` выплачивает корректно.
|
||||
5. Регресс не затронул выплаты в `dao_wallet` и `call_reward` подписанту (их адреса
|
||||
не совпадают с вольтом).
|
||||
|
||||
## Ожидаемый результат
|
||||
Тикет с получателем-вольтом невозможно создать; ранее существовавший вектор
|
||||
перманентной заморозки очереди закрыт. Прочая логика выплат без изменений.
|
||||
|
||||
## Статус
|
||||
pending
|
||||
@@ -0,0 +1,32 @@
|
||||
# Устойчивое создание 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
|
||||
Reference in New Issue
Block a user