Skip to content

Add regression test fixed - #256

Open
Mitch5000 wants to merge 46 commits into
AnchorNet-Org:Add-regression-test-FIXEDfrom
Mitch5000:Add-regression-test-FIXED
Open

Add regression test fixed#256
Mitch5000 wants to merge 46 commits into
AnchorNet-Org:Add-regression-test-FIXEDfrom
Mitch5000:Add-regression-test-FIXED

Conversation

@Mitch5000

Copy link
Copy Markdown

=================================================================
PULL REQUEST
Title:
fix: unbreak test build and validate deregister/re-register balance invariants

Base branch: main
Compare branch: fix/deregister-reregister-balance-regression-test
Commit: 24d3a20

SUMMARY
The issue asked for a regression test pinning that deregister_anchor
leaves an anchor's balances and pool.providers untouched across a
deregister/re-register cycle, that the re-registered anchor can
withdraw its preserved balance immediately, and that liquidity and
settlement actions stay blocked (AnchorNotRegistered) while the
anchor is deregistered.

Investigation found that the regression test
(test_deregister_re_register_preserves_balances_and_provider_count)
had already been added to src/test.rs in commit ae20ddc ("Add
regression test FIX"), and that production code already implements
the intended behavior:

deregister_anchor only flips the Anchor(address) flag to false via
storage::set_anchor_flag; it never touches Balance(anchor, asset)
entries or Pool state, matching its doc comment ("Existing pool
liquidity is unaffected").
register_anchor (re-registration) only sets the flag and appends to
the dedup-checked anchor list; it never resets balances.
pool.providers is counted purely from balances (do_provide
increments only when the prior balance is 0; do_withdraw decrements
only when the remaining balance hits 0), so re-registration cannot
double-count.
BUT the test was dead code: the entire test tree failed to compile at
HEAD with 19 errors, and CI had been scoped to a no-op echo while
"build/test failures are triaged" - meaning nothing in the repo,
including this fund-safety invariant, was actually being validated.

This PR repairs the test build so the whole suite (312 tests,
including the issue's regression test) compiles and runs green again,
with ZERO changes to deregister / register / liquidity / settlement
logic, exactly matching the issue's "no production code changes
expected" scope.

ROOT CAUSES OF THE BROKEN BUILD (all in test tree at HEAD)
Two read-only contract entrypoints were silently dropped by bad
merges while their tests (and docs) remained:
oldest_pending_settlement_id (added in 82c1299, dropped later)
is_min_liquidity_configured (added in 86f7a15; docs/ADMIN.md
line 47 still documents it)
Missing "extern crate alloc" and a std::collections::HashSet
import in a #![no_std] crate (7 compile errors).
quote_fee call sites in the fee proptest written against the wrong
generated-client return type (the client unwraps the contract's
Result<i128, Error> to i128).
events.last() used on soroban-sdk 25's ContractEvents, which has no
such accessor.
test_clear_operator used assert_operator_rejected! (expects a host
authorization failure) for pause/unpause/extend_instance_ttl after
the operator is revoked - but require_admin_or_operator rejects a
non-privileged caller with contract-level Error::NotAuthorized
BEFORE reaching require_auth (the same behavior
test_operator_can_renounce already pins, and the exact case the
defined-but-unused assert_caller_unauthorized! macro was built
for). The test also never restored mock_all_auths() after the
per-call set_auths overrides, which poisoned the final
admin-authorized pause call with a host auth failure.
CHANGES
src/test.rs (test-only repairs):

Linked alloc for the #![no_std] test module (extern crate alloc).
Fixed 3 quote_fee call sites to the generated client's unwrapped
i128 return in prop_fee_three_axis_interaction; silenced the unused
expected_bps binding in the same function.
Replaced std::collections::HashSet with
alloc::collections::BTreeSet (same insert/intersection/iterate/
collect semantics) in test_status_pagination_partitions_settlement_history.
test_clear_max_settlement_amount: rewrote the event assertion using
ContractEvents' Vec-based PartialEq (the idiom used by every other
event test in this file), capturing events immediately after
clear_max_settlement_amount since events().all() reflects only the
most recent top-level invocation.
test_clear_operator: switched the three assertions to
assert_caller_unauthorized! (contract-level NotAuthorized), and
restored env.mock_all_auths() before the admin-authorized calls that
follow.
src/lib.rs (restorations only; no logic changes to existing paths):

Restored is_min_liquidity_configured(asset) -> bool, a read-only
view delegating to the existing storage::has_min_liquidity,
distinguishing an explicit 0 floor from a never-configured asset.
Restored oldest_pending_settlement_id(asset) -> Option, a
read-only keeper helper returning the lowest (oldest) id among
currently Pending settlements for an asset.
Both restorations use the exact implementations previously merged
in 82c1299 and 86f7a15. Neither function mutates state; they cannot
affect balances, pools, or settlements.
README.md:

Added both restored entrypoints to the public API tables.
CHANGELOG.md:

[Unreleased] entries for the regression coverage and the
test-build repair.
ACCEPTANCE CRITERIA MAPPING
[PASS] "A regression test confirms balances and pool-provider counts
are fully preserved across a deregister/re-register cycle."
-> test_deregister_re_register_preserves_balances_and_provider_count
now compiles, runs, and passes: balance/anchor_balances/
pool.total/pool.providers asserted identical (1_000 / [(USDC,
1_000)] / 1_000 / 1) before deregister, after deregister, and
after re-register; no reset and no double-count.

[PASS] "The anchor can withdraw its preserved balance immediately
after re-registration."
-> Same test: right after re-registering (with NO new
provide_liquidity first), withdraw_all_liquidity returns 1_000,
balance drops to 0, and pool.providers drains to 0.

[PASS] "The anchor is correctly blocked from liquidity/settlement
actions while deregistered."
-> Same test: try_provide_liquidity and try_open_settlement both
return Error::AnchorNotRegistered while the anchor is
deregistered (verified independently of the existing
test_deregister_anchor_blocks_settlement).

SECURITY NOTE (per the issue)
If deregistration ever accidentally touched balance state in a future
refactor, an anchor's funds could become temporarily or permanently
inaccessible purely from an administrative registration action. This
PR makes that guard actually executable: the regression test locking
the invariant in previously could not run at all because the test
tree did not compile and CI was a no-op. It can now not silently
regress.

VALIDATION (run on the branch)
cargo check --tests : 0 errors (was 19 at HEAD)
cargo test : 312 passed, 0 failed (entire suite,
including the 64-case proptests and the
issue's regression test)
cargo fmt --all -- --check : clean
cargo build : success (Makefile "build")
cargo build --target wasm32-unknown-unknown --release :
success, 95 KB wasm artifact
(Makefile "wasm")
Confidence: 99%. Production behavior was additionally verified by
code inspection: deregister_anchor/register_anchor never touch
Balance or Pool entries, and pool.providers is balance-driven, so a
deregister/re-register cycle is provably a no-op for fund state.

FILES CHANGED (4 modified, 0 created)
M src/test.rs (+39/-16) test-build repairs
M src/lib.rs (+32) 2 read-only entrypoints restored
M README.md (+2) API table rows for the restored views
M CHANGELOG.md (+25) Unreleased entries

(test_snapshots/ run artifacts restored/cleaned; not part of the diff.)

CHECKLIST
[x] Regression test confirms balances and pool-provider counts are
fully preserved across a deregister/re-registered cycle
[x] Anchor can withdraw its preserved balance immediately after
re-registration without providing liquidity again first
[x] Anchor is blocked from provide_liquidity / open_settlement while
deregistered (AnchorNotRegistered)
[x] No production-code behavior change to deregister/register flows
[x] Full test suite compiles and passes (312/312)
[x] cargo fmt --check clean
[x] Native build and wasm32-unknown-unknown release build succeed
[x] Test-coverage preserved and extended (no tests deleted)
[x] Documentation updated (README, CHANGELOG)

Closes #156

Ugooweb and others added 30 commits July 21, 2026 23:35
closes AnchorNet-Org#169 docs: add public API compatibility checklist for reviewing contract interface changes
…nt-lifecycle-state-machine-as-a-diagram-or-table-in-the-README-FIXED
Mitch5000 and others added 16 commits July 27, 2026 07:47
Closes AnchorNet-Org#106

- Add pool_exists(env, asset) -> bool to AnchornetContract in src/lib.rs,
  delegating directly to storage::has_pool which already existed internally.
  Placed immediately after pool() in the pool-view section.

- Fix pre-existing compile error: client alias list_settlements_by_anchor_and_asset
  referenced a non-existent method name list_settlements_by_anchor_asset;
  corrected to list_settlements_by_anch_asset (the actual exported symbol).

- Add 6 regression tests in src/test.rs:
    test_pool_exists_false_before_any_liquidity
    test_pool_exists_true_after_provide_liquidity
    test_pool_exists_true_after_provide_liquidity_multi
    test_pool_exists_true_after_full_withdrawal
    test_pool_exists_is_per_asset
    test_pool_exists_consistent_with_pool_getter

- Update README.md contract interface table with the new read-only entrypoint.

pool() error-returning behavior and Error::PoolNotFound are unchanged.
No authorization required (pure read view, no state mutation).
…view

feat: add pool_exists(asset) -> bool public view entrypoint
…st-that-a-mid-batch-failure-FIXED

Add regression test that a mid-batch failure FIX
…_override-FIXED

Add has_asset_fee_override FIX
…nchorNet-Org#248)

Implements settlement_status(env, id) -> Result<SettlementStatus, Error> as described in issue AnchorNet-Org#112.

- Added settlement_status entrypoint in src/lib.rs (near settlement/settlement_exists) that returns just the SettlementStatus field via storage::get_settlement, or Error::SettlementNotFound for a missing id.
- Added src/test.rs coverage: tests for Pending, Executed, Cancelled, Expired variants and for a missing id (SettlementNotFound).
- Updated the README settlement table to document the new settlement_status(id) view.

Relates to: AnchorNet-Org#112
…nchorNet-Org#251)

Add renounce_operator(env, caller) so the current operator can step
down without admin involvement, complementing the existing admin-only
clear_operator().

- Precondition checks (has_operator, caller == operator) execute before
  caller.require_auth(), returning clean contract errors (NoOperator,
  NotAuthorized) for wrong callers while keeping require_auth() as the
  cryptographic security boundary
- Shares storage::clear_operator() with the admin path
- Emits event with topic ("renounce",), distinct from admin's
  ("op_clear",), so off-chain systems can distinguish self-initiated
  exit from admin-initiated removal
- Four new tests: operator can renounce, non-operator callers (admin,
  stranger) rejected, admin forging operator's address hits host auth
  abort, renouncing with no operator fails with NoOperator
- Updated EVENTS.md, README.md operator tables, ADMIN.md auth matrix
* refactor: use shared require_valid_fee helper for set_fee and set_asset_fee

* test: add bounds check tests for set_asset_fee

---------

Co-authored-by: Truphile <salidmonreal@gmail.com>
* refactor: use shared require_valid_fee helper for set_fee and set_asset_fee

* test: add bounds check tests for set_asset_fee

* test: add settlement_count_and_list_consistency test

---------

Co-authored-by: Truphile <salidmonreal@gmail.com>
…nt (AnchorNet-Org#254)

Add `prop_settlement_ids_monotonic_and_gapless` proptest that generates
randomized sequences of settlement lifecycle operations (open, execute,
cancel, cancel_expired) across multiple assets and anchors, asserting:
- Settlement IDs are strictly monotonic and gapless (1, 2, 3, ...)
- settlement_count() always equals the number of open_settlement calls

The helper struct IdMonotonicSettlement mirrors on-chain state locally
to filter pending and expired settlements during the randomized sequence.

closes AnchorNet-Org#155
Add a dedicated ("exited", provider, asset) event that fires when a
provider's balance in an asset reaches exactly zero via a withdrawal —
the mirror image of the asset_onboarded event on the provide side.

Changes:
- src/events.rs: add provider_exited() helper with topic
  ("exited", provider, asset) and empty data
- src/lib.rs: call events::provider_exited() in do_withdraw when
  remaining == 0, after the existing liquidity_withdrawn event
- src/test.rs: add three regression tests covering full exit fires the
  event, partial withdrawal does not, and re-entry + re-exit fires it
  again; update two existing parity tests to include the new event
- README.md: document ("exited", provider, asset) in the events
  at-a-glance list

Off-chain indexers can now react to a dedicated signal when a provider
fully exits a pool rather than reconstructing that signal by comparing
balances across withdrawal events.
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.