# TASK — Фикс: сделать vault_token обычным ATA-токен-счётом (убрать seeds = PDA) Репозиторий: `smart-updown-token`. Файлы: `program/programs/smart-updown/src/instructions/create_bet.rs` и `.../close_bet.rs`. ## Проблема (обнаружено на localnet E2E) Токен-аккаунт ваулта объявлен так: ```rust #[account( mut, seeds = [GLOBAL_SEED, VAULT_SEED], // ← требует адрес == PDA([global,vault]) )] pub vault_token: Account<'info, TokenAccount> ``` Anchor проверяет, что **адрес `vault_token` == PDA([global,vault])**. Но казённый (escrow) токен-счёт у нас — это ATA от владельца `vaultPda`: адрес `getAssociatedTokenAddress(mint, vaultPda)`, который НЕ равен PDA. Отсюда `Error Code: ConstraintSeeds` — перевод в ваулт невозможен. У `bettor_token` такой проблемы нет (там обычный `Account`, адрес = ATA игрока). ## Что исправить ### 1. `create_bet.rs` У `vault_token` **убрать блок `seeds = [GLOBAL_SEED, VAULT_SEED]`** — оставить просто: ```rust #[account(mut)] pub vault_token: Account<'info, TokenAccount>, ``` (оставить поле `bump` больше не нужно — удалить его из struct, если он был). Это сделает адрес любого токен-счёта (ATA ваулта) приемлемым. ### 2. `close_bet.rs` То же самое: у `vault_token` убрать `seeds = [...]`. НО: раз адрес больше не фиксируется seeds, передавать/подписывать перевод нужно от **владельца-пользователя (vaultPda)**. В `close_bet` AUTHORITY перевода остаётся владелец аккаунта (поле `owner` токен-счёта). Проверить: signer_seeds `[GLOBAL_SEED, VAULT_SEED, bump]` должны по-прежнему давать vaultPda (это и есть владелец ATA). Так как сигнатура от PDA не меняется, seed-фразы в `close_bet.rs` (для подписи CPI) СТАВЯТСЯ из `ctx.accounts.vault_token` owner. Возможно понадобится отдельный аккаунт `vault_authority: PDA([global,vault])`, чтобы передать в signer seeds — оценить и сделать аккуратно (стандартный Anchor escrow). ### 3. Пересборка и проверка - `anchor build` зелёный. - IDL перегенерировать (`anchor idl build`), синхронизировать `relayer/idl/smart_updown.json`. - `npm run typecheck` / `npm test` в `relayer/` — зелёные (если тесты проверяют seeds — обновить). ## Важно (архитектурно) `vault_token` — это ATA от владельца `vaultPda` (адрес `getAssociatedTokenAddress(mint, vaultPda)`). Контракт НЕ должен требовать конкретного адреса — только владельца-подпись для withdraw. Всё, что нужно — чтобы в `close_bet` authority (тот, кто подписывает перевод из ваулта) был **vaultPda** (владелец ATA), а не адрес аккаунта. ## НЕ делать - Не трогать логику ставок/цен. - Не трогать релейер (он уже передаёт правильный ATA-адрес). - Не коммитить. ## Проверка успеха - `anchor build` + IDL обновлён. - На localnet: передача `vault_token` = ATA (`getAssociatedTokenAddress(mint, vaultPda)`), create_bet принимает ставку, close_bet выплачивает (signer — vaultPda). E2E проходит.