Skip to content

feat(scenarios): add GoonFi state preparation - #13

Open
92Infinitus92 wants to merge 8 commits into
feat/bisonfi-supportfrom
feat/goonfi-support
Open

feat(scenarios): add GoonFi state preparation#13
92Infinitus92 wants to merge 8 commits into
feat/bisonfi-supportfrom
feat/goonfi-support

Conversation

@92Infinitus92

@92Infinitus92 92Infinitus92 commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #8 — GoonFi is the same mechanism class as BisonFi and Tessera (PMM, no IDL) and reuses the raw-layout engine BisonFi introduced.

  • Two raw-layout accounts per market: a 32-byte external price oracle (bid, ask, freshness, decay) and the 2048-byte market holding the reference band that guards it. Four templates over the pair — price, reference band, freshness, stale quote — plus a live catalog read from program accounts and validated at creation.
  • Two builders. Price moves the oracle bid and ask together with the market's reference band and a persistent freshness stamp, since the deployed program rejects a decoupled move with 0x24. Liquidity resolves both token vaults from the market's own pointers and scales their balances through the generic spl-token-account-balance template.
  • Three MCP tools on the generic scenario path: list_goonfi_markets, create_goonfi_price_scenario and create_goonfi_liquidity_scenario. No protocol HTTP endpoints and no custom RPC methods.
  • The Slot raw encoding now takes a width, so GoonFi's 4-byte freshness field no longer clobbers the decay multiplier stored beside it. Existing 8-byte slot fields are unchanged.
  • The oracle carries no discriminator, so the raw-layout owner predicate is what keeps a write out of a foreign 32-byte account, and every builder resolves the oracle through the market's own pointer rather than trusting a caller-supplied address.
  • Verified against the deployed program on a fork: drained vaults reject with 0x1, a dislocated quote with a coupled band fills at the prepared price, an aged oracle rejects with 0x15, and a price moved out of its band rejects with 0x24.
  • The shared live-test helper duplicates the Tessera branch's on purpose; they fold together when the branches converge.

Greptile Summary

The PR adds GoonFi market discovery and price/liquidity scenario preparation using raw account layouts, together with MCP tools and protocol tests.

  • Adds validated market, oracle, mint, and vault discovery.
  • Adds coupled price, reference-band, freshness, and liquidity overrides.
  • Adds GoonFi MCP tools, registry integration, documentation, and live-test coverage.
  • Updates raw slot encoding to support width-specific freshness fields.

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Important Files Changed

Filename Overview
crates/core/src/scenarios/protocols/goonfi/v1/price.rs Adds coupled GoonFi price preparation and now binds the supplied market, base-vault, and oracle tuples through pointer and authority checks.
crates/core/src/scenarios/protocols/goonfi/v1/liquidity.rs Adds vault-balance scaling while validating each supplied address against market-derived pointers, mints, token owners, and market authority.
crates/core/src/scenarios/protocols/goonfi/v1/markets.rs Adds live market discovery with per-market decoding and validation failures isolated from independently valid catalog entries.
crates/mcp/src/surfpool/mod.rs Exposes GoonFi catalog, price, and liquidity tools using accounts resolved from the selected market.
crates/types/src/scenarios.rs Extends raw slot encoding with an explicit width so four-byte freshness writes preserve adjacent fields.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart LR
  U[MCP request] --> M[Fetch selected market]
  M --> P[Resolve oracle and vault pointers]
  P --> V[Validate owners, layouts, addresses, mints, and authorities]
  V -->|Price| PS[Build price, reference-band, and freshness overrides]
  V -->|Liquidity| LS[Scale selected vault balances and add freshness override]
  PS --> S[Register scenario]
  LS --> S
Loading

Reviews (7): Last reviewed commit: "fix(goonfi): bind account inputs to mark..." | Re-trigger Greptile

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown

Two improvements in the PR:

  • markets.rs:146: One missing oracle/mint or invalid market aborts the entire catalog. Skip invalid entries and report diagnostics so an obsolete market cannot hide all valid markets.
  • liquidity.rs:178: Vault validation accepts any token-program-owned account with at least 72 bytes—including an 82-byte mint. Unpack a token account and verify its mint matches the corresponding market mint before reading its balance.

Tests could not run: Rustup attempted to write into a read-only toolchain directory.

@92Infinitus92 92Infinitus92 self-assigned this Sep 9, 2026
Comment thread crates/core/src/scenarios/protocols/goonfi/v1/markets.rs Outdated
Comment thread crates/core/src/scenarios/protocols/goonfi/v1/price.rs
@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
  • [P2] Validated market/oracle pairing remains mutableprice.rs:65. #[non_exhaustive] prevents external struct literals, but callers can still assign market.oracle = another_oracle after validation. The builder then modifies that oracle alongside the original market’s reference band, producing an inconsistent scenario. Make both fields private and expose read-only getters.

The catalog isolation issue from the earlier review is fixed in the latest commit. Review was static; tests were not run.

@github-actions

github-actions Bot commented Sep 9, 2026

Copy link
Copy Markdown
  • [P2] Account validation still lacks address bindingprice.rs:90. validate checks the supplied oracle’s layout but cannot establish that it belongs to the market’s oracle pointer. Private fields do not close this gap for direct library callers. Accept keyed accounts and compare addresses, or fetch the referenced account within validation.

  • [P2] Liquidity scaling can use another vault’s balanceliquidity.rs:99. Any token account with the expected mint passes validation. Passing another market’s vault calculates the percentage from its balance, then writes that amount to this market’s vault—potentially increasing liquidity during a requested drain. Validate supplied vault addresses against the market pointers and add a mismatch regression test.

Tests could not run: rustup attempted to write to a read-only directory.

Comment thread crates/core/src/scenarios/protocols/goonfi/v1/price.rs
GoonFi is a two-account dark AMM with no IDL: a 32-byte external price oracle
plus a 2048-byte market carrying the reference band that guards it.

- Four raw-layout templates over the two accounts (price, reference band,
  freshness, stale quote), plus a live market catalog read from program accounts.
- Two builders. Price moves the oracle bid and ask together with the market's
  reference band and a persistent freshness stamp, because the deployed program
  rejects a decoupled move with 0x24. Liquidity resolves both token vaults from
  the market's own pointers and scales their balances.
- Three MCP tools on the generic scenario path: list_goonfi_markets,
  create_goonfi_price_scenario and create_goonfi_liquidity_scenario. No protocol
  HTTP endpoints.
- The Slot raw encoding now takes a width, so the 4-byte freshness field no
  longer clobbers the decay multiplier stored beside it.
- Live gated tests against the deployed program. The shared live-test helper
  duplicates the Tessera branch's on purpose; they fold together when the
  branches converge.
- Catalog discovery skips a market that fails validation with a warning instead of
  aborting the whole scan, so one obsolete market can no longer hide every valid one.
  An empty catalog from a program that does own markets stays an error.
- Vault balances are read through TokenAccount::unpack and checked against the market's
  own mint: an owner-and-length check also admits an 82-byte mint, whose bytes at the
  amount offset would be misread as a balance.
- GoonfiMarket is non_exhaustive, so a market and its oracle can only be paired through
  validate, which reads the oracle from the market's own pointer.
`non_exhaustive` only blocked building a GoonfiMarket from scratch outside the crate;
the fields stayed public, so a caller could still re-point a validated pair's oracle.
Making both private leaves `validate` as the only way to pair a market with an oracle,
and it reads that oracle from the market's own pointer.
The fields are private, so a caller that legitimately needs to know which market and
oracle a validated pair refers to had no way to ask.
A market account does not record its own address, so `validate` had to take the caller's
word that the address and the data describe the same market. Its vaults do record it: a
GoonFi vault is a token account whose authority is the market. `validate` now takes the
base vault the market itself names and compares that authority, the same shape of
cross-check the pump graduation builder makes through its curve vault's mint. The
liquidity builder applies it too, from accounts it already holds.

Neither path costs an extra round trip: discovery carries the base vault alongside the
mints and oracle so it batches with them, and the MCP market fetch reads it in the same
call as the oracle. Verified against all 33 live markets - every one names its market as
the base vault's authority.
The BisonFi branch was squashed and renamed `load_protocol_overrides_without_idl` to
`load_raw_layout_overrides`; GoonFi registers its two raw account shapes through it, the
same call BisonFi makes for its own.
Comment thread crates/core/src/scenarios/protocols/goonfi/v1/liquidity.rs Outdated
The balance is read from the account passed in but written to the vault address decoded
from the market, so a vault of the right mint belonging to another market would scale the
wrong balance into this one - a requested drain could top the vault up instead. The
authority check now lives inside the balance read, where it covers the quote side too, and
the base-only call it replaces is gone.
Comment thread crates/core/src/scenarios/protocols/goonfi/v1/price.rs Outdated
Comment thread crates/core/src/scenarios/protocols/goonfi/v1/liquidity.rs
Validate vault and oracle addresses against the market's pointers before
reading balances or constructing overrides. Preserve the existing RPC reads
and generic scenario templates.

Add mismatch regressions and update MCP, discovery, and live-test callers.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant