Verify Token-2022 settlement against the whole existing suite - #121
Draft
kaze-cow wants to merge 1 commit into
Draft
Verify Token-2022 settlement against the whole existing suite#121kaze-cow wants to merge 1 commit into
kaze-cow wants to merge 1 commit into
Conversation
kaze-cow
changed the base branch from
kaze/sc-153-token-2022-program
to
kaze/sc-153-token-2022-settle
August 28, 2026 07:22
kaze-cow
force-pushed
the
kaze/sc-153-token-2022-tests
branch
from
August 28, 2026 07:22
b667e36 to
9f512c4
Compare
This was referenced Aug 28, 2026
The Token-2022 paths are worth little if they only hold for the handful of cases someone thought to write twice, so instead of a parallel suite this reruns the suite that already exists against the second program. `common::also_under_token_2022!(some_test)` sits in front of a test and generates `some_test_token_2022`, which runs the same body with Token-2022 as the thread-local active program. Nothing in the body changes: the token helpers build against the program that owns the account they are handed, and `payer_signed_tx` / `signed_tx` repoint the legacy program id in every instruction they assemble. 75 tests are covered this way, across buffer creation, reclamation, order settlement, pushes, and limit prices -- error paths as much as happy ones. A settlement pair is the exception to that repointing. Its token programs are slots named by value rather than accounts to be rewritten, and rewriting the legacy slot in place would leave the pair in an order `TokenPrograms::validate` rejects. `common::token_programs()` names the slots the active program wants instead, and the generated tests pass that where they used to write `TokenPrograms::SPL_TOKEN`. Naming the test in front of it, rather than wrapping the body, keeps the indentation and makes a stale name a compile error instead of a test that quietly stopped being generated. A test that can only hold under one program (one pinned to the legacy native mint) goes without and says why, as do the suites whose instructions name no token program at all. Three tests are Token-2022-only, covering what has no legacy analogue -- a buffer for a mint with a `TransferFeeConfig`, which needs a `TransferFeeAmount` on every account holding it and so must be longer than the base layout: - `creates_buffer_sized_for_a_mint_with_extensions` - `recreating_an_extension_mint_buffer_is_idempotent` - `reclaims_a_buffer_sized_for_an_extension_mint` `bench-report.json` gains the CU, account, and transaction-byte readings for every generated test. Token-2022 costs more per instruction, as expected from the longer accounts and the extension-aware transfer path. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
kaze-cow
force-pushed
the
kaze/sc-153-token-2022-settle
branch
from
August 28, 2026 08:29
7af181d to
35bb3fe
Compare
kaze-cow
force-pushed
the
kaze/sc-153-token-2022-tests
branch
from
August 28, 2026 08:30
9f512c4 to
223bd0d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #128, which is stacked on #120 — review those first; this PR targets #128's branch, so the diff shown here is tests only.
Approach
The Token-2022 paths in #120 and #128 are worth little if they only hold for the handful of cases someone thought to write twice. So rather than a parallel Token-2022 suite, this reruns the suite that already exists against the second program.
common::also_under_token_2022!(some_test)sits in front of a test and generatessome_test_token_2022, which runs the same body with Token-2022 as the thread-local active program:Nothing in the body changes. The token helpers in
tests/common/token.rsbuild against the program that owns the account they are handed (token::program_of), andpayer_signed_tx/signed_txrepoint the legacy program id in every instruction they assemble. The active program is a thread-local, which is a per-test value because the harness runs each test on its own thread.Naming the test in front of it, rather than wrapping the body, keeps the body's indentation and makes a stale name a compile error instead of a test that quietly stopped being generated.
The settlement pair is the exception
BeginSettleandFinalizeSettlename their token programs as slots by value, not as accounts to be rewritten. Repointing the legacy slot in place would leave the pair in an orderTokenPrograms::validaterejects — slot 0 must hold SPL Token or the placeholder, never Token-2022.So
common::token_programs()names the slots the active program wants, and the generated tests pass that where they used to writeTokenPrograms::SPL_TOKEN.aim_at_active_token_programstill handles the single-slot instructions,CreateBufferandReclaimBuffer.Coverage
75 tests are generated this way, across buffer creation, buffer reclamation, order settlement, pushes, and limit prices — error paths as much as happy ones (wrong bumps, fabricated accounts, owner mismatches, duplicate orders, over-delegation, cancelled and expired orders, push/order count mismatches).
create_bufferreclaim_bufferbegin_settle_ordersfinalize_settle_pushessettle_limit_pricesDeliberately excluded, each saying why in place: a test pinned to the legacy native mint, which can only hold under one program; and the suites whose instructions name no token program at all (
Initialize,CreateOrder,ReclaimOrder,TransferAuthority), which have nothing to vary.settle_token_programs(added in #128) is likewise left alone — it already names both programs explicitly.Three tests are Token-2022-only, covering what has no legacy analogue. They use a mint carrying a
TransferFeeConfig, which requires aTransferFeeAmounton every account holding it and so forces a token account longer than the base layout — the shape that motivates mint-dependent buffer sizing:creates_buffer_sized_for_a_mint_with_extensionsrecreating_an_extension_mint_buffer_is_idempotentreclaims_a_buffer_sized_for_an_extension_mintUnit tests for the dispatch and sizing logic itself live with the implementation in #120 and #128.
Harness notes
The legacy program's instruction builders reject any other program id, so the helpers build against the legacy program and are retargeted on the way out. Both programs encode these instructions identically, so what arrives is exactly what the other program expects.
aim_at_active_token_programonly rewrites the legacy address, so an instruction a test deliberately pointed somewhere else — at an unrelated program, to be rejected — is left alone. It can go away once the instruction builders take the token program as a parameter.common::buffer::ensure_buffer_existsnames its program outright rather than leaving it to the active one, because a settlement mixing the two programs builds buffers under both within a single test.Compute cost
bench-report.jsongains readings for every generated test. Token-2022 costs more per instruction, as expected from the longer accounts and the extension-aware transfer path — e.g.settle/settles_multiple_orders23,257 → 27,350 CU,create_buffers/happy_path_creates_initialized_buffer_token_account10,361 → 11,695 CU. Transaction bytes and account counts are identical between the two.Verification
🤖 Generated with Claude Code