62 lines
3.9 KiB
Markdown
62 lines
3.9 KiB
Markdown
# 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 проходит. |