fix: vault как ATA + фандинг беттора; E2E на localnet ok

This commit is contained in:
Caffeine
2026-09-10 02:12:07 +03:00
parent fb9a7f4e8b
commit f937c8993d
15 changed files with 267 additions and 148 deletions
+62
View File
@@ -0,0 +1,62 @@
# 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<TokenAccount>`, адрес = 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 проходит.