Skip to content

test: move business-rule coverage off-node (ENG-470)#515

Merged
peer2f00l merged 6 commits into
devfrom
feature/eng-470-pure-unit-extraction-move-business-rule-tests-off-the-node
Jul 20, 2026
Merged

test: move business-rule coverage off-node (ENG-470)#515
peer2f00l merged 6 commits into
devfrom
feature/eng-470-pure-unit-extraction-move-business-rule-tests-off-the-node

Conversation

@peer2f00l

@peer2f00l peer2f00l commented Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • move deterministic market, vault, migration, funding-bridge, and relayer business-rule coverage from sandbox tests into pure unit tests
  • centralize relayer market-ID validation and universal-account migration version-guard cases
  • retain targeted on-node boundary coverage for treasury dry-run safety, vault gateway serialization/routing, all universal-account signer formats, constructor transactions, and legacy state-shape failures

Test plan

  • affected pure unit tests
  • retained on-node boundary smoke tests
  • four-way follow-up code review across common/vault, universal-account migrations, funding bridge, and relayer routes; no actionable findings

Linear: https://linear.app/templar-protocol/issue/ENG-470/pure-unit-extraction-move-business-rule-tests-off-the-node


This change is Reviewable

peer2f00l and others added 4 commits July 20, 2026 19:30
Move node-backed tests that only assert pure logic into fast off-node
tests, keeping on-node only genuine contract-boundary crossings.

universal-account:
- universal_account.rs: 68 -> 10 node cases. The pure ExecuteArgs::verify
  table already covers all signature formats x every param/domain/payload
  mismatch (and env::ed25519_verify/sha256 run natively in unit tests), so
  the 7-signer x 3-mode grids re-proved pure logic on-chain. Keep one
  happy-path per host-crypto family (passkey/ed25519_raw/eip191), a
  constructor-execute test, and the 5 boundary singles. Delete skip_nonce
  / reuse_nonce (subsumed by failed_execute / replayed_nonce + the pure
  table); drop the `migrated` dimension (covered by migration.rs).
- migration.rs: replace 12 version-guard node cases with 6 pure
  #[should_panic] tests in state::migration::tests (byte-exact messages),
  keeping the one on-chain-only case (bugged-0.4.0 borsh deserialize).

vault: delete 3 happy_path.rs node dupes (duplicate supply queue, and the
two fee-cap rejections) whose in-process src/tests.rs versions are strict
supersets.

Verified: fmt/clippy clean, 6 pure guard tests pass + mutate-to-fail
confirmed, node subset 40/40 green.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…f-node (ENG-470)

Continue the pure-unit extraction: move node-backed tests that only assert
pure functions into fast off-node #[test]s, keeping on-node only genuine
contract-boundary crossings.

- common: pure minimum_acceptable_liquidation_amount rstest (liquidation-math
  prep; liquidatable_collateral already covered).
- vault: 2 pure set_fees conversions in src/tests.rs (decrease-applies-
  immediately, growth-rate accept+persist) replacing node fee_decrease_immediate
  and set_fees_accepts_max_total_assets_growth_rate.
- relayer: extract validate_market_ids (generic hasher + iterator param) shared
  by both price handlers; 3 node rejection tests -> 3 pure route::tests.
- funding-bridge: pure App::new tests + DRY Args::test_valid(); drop node
  test_app_initialization and test_near_handler_dry_run (dry-run covered by
  treasury.rs test_send_tokens_dry_run).
- proxy-oracle: init_writes_current_state_version async->pure testing_env!.

Verified: cargo fmt --all --check clean, clippy -D warnings clean on touched
crates, all pure tests pass, mutate-to-fail confirmed each extraction, node
test targets compile.

Market suite left untouched: it was already curated by the ENG-388 rewrite
(pure math already off-node, integration tests deliberately keep only
node-worthy flows), so the ticket's ~55-extractable estimate no longer holds.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
A second review flagged that deleting both node fee tests left no on-node
coverage of the vault_set_fees/vault_get_fees path — the Fees<SU128> wire
conversion, gateway dispatch, and deployed-state persistence. Per ENG-470's
"keep one boundary smoke per flow", restore a single consolidated smoke that
sets a fee decrease + a growth-rate cap through the gateway and reads them
back. The immediate-vs-timelocked decision stays covered off-node by the pure
set_fees_* tests in src/tests.rs.

Verified: passes on-node (fee_changes_round_trip_through_the_gateway, 26.5s).

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
A second, more thorough review found four extractions that dropped genuine
boundary coverage (not equivalent to the pure replacements). Restore the
minimum on-node coverage per ENG-470's "keep one boundary smoke per flow":

- universal-account: re-add eip712 + sep53 to execute_advances_nonce so all
  five signing formats init through the deployed `new` ABI, persist, list, and
  execute on-node (verify stays pure). eip712 had no remaining node coverage.
- universal-account: execute_on_create_runs_constructor_transactions now
  asserts `new` installs the controller key (nonce 0) alongside the constructor
  batch — previously it only checked the batch ran.
- funding-bridge: restore test_near_handler_dry_run, which proves the
  safety invariant that a dry-run submits no real transfer (balance unchanged)
  — the pure test only checks the returned marker.
- vault: restore one narrow supply_queue_mustnt_have_duplicates gateway smoke
  (curator auth + account->MarketId resolution + duplicate panic); the
  exhaustive rule stays pure in src/tests.rs.

Declined (documented in the plan): 0.2.0 migrate-then-execute (covered in
combination by from_0_2_0 state + from_0_4_0_unbrick_v1 V2 execution) and
relayer handler-wiring tests (App::new needs live Postgres+gateway = a node
test, contra ENG-470; glue is trivial and still hit by success-path tests).

Verified: all four pass on-node; cargo fmt --all --check clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: e0adf86e-4f97-4521-8f82-8cf2742edd98

📥 Commits

Reviewing files that changed from the base of the PR and between 21ba7a0 and 5512d55.

📒 Files selected for processing (3)
  • common/src/market/configuration.rs
  • service/funding-bridge/tests/tests.rs
  • service/relayer/tests/relayer.rs

📝 Walkthrough

Summary

Moves deterministic business-rule coverage for market logic, universal-account migrations, funding-bridge config/init, and relayer market-ID validation from sandbox-style tests into pure unit tests, while keeping on-node boundary smoke coverage for treasury/vault/gateway safety and legacy state-shape failures.

Key changes:

  • Market rules tests: Expanded Pyth oracle test fixtures to construct Price/PythTimestamp, updated price_pair helper to use explicit publish times, and extended minimum_acceptable_liquidation_amount parametrized coverage including a zero spread (no discount) case.
  • Universal-account:
    • Tightened migration tests: replaced broad invalid-sequence matrix with a focused 0.4.0→V0→V1 deserialize failure regression, and simplified/remove redundant negative-path cases.
    • Added migration version-guard negative coverage asserting the migration variants panic on stored version mismatch.
    • Simplified constructor/execution harness: removed “migrated” branching from setup, refactored around ExecuteOnCreate, replaced nonce-advancement test to drop migration flag, and added explicit constructor transaction execution semantics when execute is provided.
  • Proxy-oracle near migration test: Rewrote init_writes_current_state_version to run synchronously in-process using direct contract methods instead of sandbox async harness + JSON views.
  • Vault (gateway-based):
    • Added gateway-focused tests for fee behavior (including fee decrease immediacy and max-growth-rate cap “tightening” behavior).
    • Updated governance happy-path coverage to assert fee + growth-cap round-trip through the gateway.
    • Added a gateway boundary assertion that supply queue rejects duplicates.
  • Funding-bridge:
    • Added unit tests for App::new health/config error behavior (including near_treasury_account: None returning FundingError::ConfigError).
    • Added test-only Args::test_valid() to centralize unit-test configuration.
    • Refactored integration tests to construct NearHandler directly; strengthened dry-run safety by snapshotting both treasury and recipient balances.
  • Relayer:
    • Centralized market-ID validation for price routes via a shared validate_market_ids + MarketIdRejection error with consistent reason() strings.
    • Updated both get_market_prices and update_prices to use the shared validator and return SimpleResponse::Rejected based on the rejection reason.
    • Adjusted test assertions structure for rejection handling (logic unchanged).

Review focus

  • Migration/version-guard correctness & ordering: Verify stored-version mismatch guards execute before any state deserialization/read, and that the panic behavior in tests matches intended production invariants (upgrade safety).
  • Relayer input validation: Ensure validate_market_ids semantics (empty request + unknown market IDs) and returned rejection reasons are consistent across both routes; confirm allowlist/known-set source is unchanged.
  • Universal-account execute-on-create semantics: Confirm nonce/controller-key expectations are correct for all ExecuteOnCreate variants and that refactoring removed only redundant migration coverage (no behavioral loss).
  • Gateway/vault boundary assumptions: Review the new gateway round-trip fee/cap tests to ensure they truly cover the gateway serialization/routing path and don’t mask contract-side edge cases.
  • Treasury dry-run safety: Confirm the stronger balance snapshot in funding-bridge integration tests still reflects the intended invariant (no balance movement on dry-run).
  • Smart-contract risk index: For any change touching migration guards, state versioning, or relayer validation, cross-check against known classes of issues in the “smart-contract-vulnerabilities” index (e.g., improper upgrade/migration guards, authorization/validation gaps, inconsistent rejection paths).

Walkthrough

The pull request expands market, contract, vault, funding-bridge, and relayer test coverage. It centralizes relayer market validation, refactors universal-account setup around constructor execution, adds migration regressions, and moves funding-bridge initialization checks into unit tests.

Changes

Market liquidation validation

Layer / File(s) Summary
Timestamped liquidation amount coverage
common/src/market/configuration.rs
Tests construct timestamped oracle prices and cover multiple liquidation amount calculations, including zero spread.

Contract state and execution tests

Layer / File(s) Summary
Proxy initialization state checks
contract/proxy-oracle/near/contract/tests/migrate_v0.rs
Proxy initialization is tested synchronously with direct contract calls for state version and migration status.
Universal-account migration failure coverage
contract/universal-account/tests/migration.rs, universal-account/src/state/migration.rs
Migration tests focus on deserialization failures and stored-version mismatch panics.
Constructor execution test setup
contract/universal-account/tests/universal_account.rs
Universal-account tests use constructor initialization directly and verify constructor execution, keys, and nonce behavior.

Vault governance test coverage

Layer / File(s) Summary
Fee and growth-rate governance behavior
contract/vault/near/src/tests.rs, contract/vault/near/tests/governance.rs
Tests cover immediate fee tightening and gateway round trips for performance fees and growth-rate caps.
Gateway supply queue validation
contract/vault/near/tests/happy_path.rs
Gateway tests reject duplicate markets in the supply queue and remove superseded fee tests.

Funding bridge initialization tests

Layer / File(s) Summary
Shared test configuration and app construction
service/funding-bridge/src/config.rs, service/funding-bridge/src/app.rs
A shared test configuration supports application construction tests for valid and missing treasury settings.
Integration test responsibility split
service/funding-bridge/tests/tests.rs
Integration tests remove app-construction setup while documenting the on-node dry-run invariant.

Relayer market validation

Layer / File(s) Summary
Centralized market-ID validation contract
service/relayer/src/route/mod.rs
Routes gain shared empty and unknown market-ID validation with structured rejection reasons and unit tests.
Route rejection wiring
service/relayer/src/route/update_prices.rs, service/relayer/src/route/get_market_prices.rs, service/relayer/tests/relayer.rs
Both price routes use centralized validation while preserving rejection reason assertions.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: carrion256

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/eng-470-pure-unit-extraction-move-business-rule-tests-off-the-node

Warning

Review ran into problems

🔥 Problems

Errors were encountered while retrieving linked issues.

Errors (1)
  • LINEAR integration encountered authorization issues. Please disconnect and reconnect the integration in the CodeRabbit UI.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
service/funding-bridge/src/config.rs (1)

165-196: 🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Compile this fixture only for tests.

Args::test_valid() is test-only, but this impl is compiled in non-test builds. That keeps a test private-key literal and unwrap() calls in production Rust, and a future fixture typo could become a panic if the helper is reused. Gate the method or impl with #[cfg(test)].

As per coding guidelines, Rust code must not introduce unwrap() in non-test code unless a documented invariant makes it safe.

Proposed fix
-impl Args {
+#[cfg(test)]
+impl Args {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@service/funding-bridge/src/config.rs` around lines 165 - 196, Gate the
test_valid method in impl Args with #[cfg(test)] so the fixture, private-key
literal, and unwrap calls are compiled only for test builds. Keep the existing
fixture behavior unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@common/src/market/configuration.rs`:
- Around line 647-668: The test helper price_pair currently hardcodes identical
exponents and decimal arguments, so it cannot exercise decimal normalization.
Update price_pair and its callers to accept distinct collateral and borrow
decimal/exponent values, then add assertions covering unequal scales while
preserving the existing equal-scale cases and checking arithmetic edge behavior
in the related common tests.

In `@service/funding-bridge/tests/tests.rs`:
- Around line 162-165: Strengthen the dry-run accounting assertion in the node
smoke test by capturing both treasury and recipient balances before invoking the
transfer and comparing both after the call. Update the existing dry-run test
flow around the balance checks so it verifies neither account changes,
preserving the end-to-end no-transfer invariant.

In `@service/relayer/tests/relayer.rs`:
- Around line 586-588: Restore handler-level regression coverage for both
/update_prices and /get_market_prices, verifying each route invokes
validate_market_ids and returns the expected SimpleResponse::Rejected reason for
empty or unknown markets. Keep the tests lightweight and retain the existing
pure validation tests.

---

Outside diff comments:
In `@service/funding-bridge/src/config.rs`:
- Around line 165-196: Gate the test_valid method in impl Args with #[cfg(test)]
so the fixture, private-key literal, and unwrap calls are compiled only for test
builds. Keep the existing fixture behavior unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 6eccd6c1-2cf1-4366-8bab-d1a9cf48673e

📥 Commits

Reviewing files that changed from the base of the PR and between e4b6b2c and 21ba7a0.

📒 Files selected for processing (15)
  • common/src/market/configuration.rs
  • contract/proxy-oracle/near/contract/tests/migrate_v0.rs
  • contract/universal-account/tests/migration.rs
  • contract/universal-account/tests/universal_account.rs
  • contract/vault/near/src/tests.rs
  • contract/vault/near/tests/governance.rs
  • contract/vault/near/tests/happy_path.rs
  • service/funding-bridge/src/app.rs
  • service/funding-bridge/src/config.rs
  • service/funding-bridge/tests/tests.rs
  • service/relayer/src/route/get_market_prices.rs
  • service/relayer/src/route/mod.rs
  • service/relayer/src/route/update_prices.rs
  • service/relayer/tests/relayer.rs
  • universal-account/src/state/migration.rs

Comment thread common/src/market/configuration.rs
Comment thread service/funding-bridge/tests/tests.rs Outdated
Comment thread service/relayer/tests/relayer.rs Outdated
@peer2f00l
peer2f00l merged commit acb3d33 into dev Jul 20, 2026
23 of 24 checks passed
@peer2f00l
peer2f00l deleted the feature/eng-470-pure-unit-extraction-move-business-rule-tests-off-the-node branch July 20, 2026 22:27
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