Skip to content

test(bond): enforce and verify bond lifecycle authorization boundaries #1272 - #1304

Merged
Baskarayelu merged 1 commit into
CredenceOrg:mainfrom
olacodes-01:fix/1272-bond-lifecycle-auth-boundaries
Aug 29, 2026
Merged

test(bond): enforce and verify bond lifecycle authorization boundaries #1272#1304
Baskarayelu merged 1 commit into
CredenceOrg:mainfrom
olacodes-01:fix/1272-bond-lifecycle-auth-boundaries

Conversation

@olacodes-01

Copy link
Copy Markdown
Contributor

Summary

Closes #1272

Enforce and verify the bond lifecycle caller-permission (authorization)
boundaries consistently across creation, increase, cooldown, exit, and
liquidation.

Auditing the existing entry points confirmed that every state-mutating
lifecycle path already gates itself on the correct authenticated address:

Lifecycle phase Entry point(s) Authority checked before mutation
Creation create_bond identity.require_auth()
Increase top_up, extend_duration identity.require_auth()
Cooldown request_cooldown_withdrawal / execute_cooldown_withdrawal / cancel_cooldown identity.require_auth()
Exit withdraw / withdraw_early / withdraw_bond / request_withdrawal / renew_if_rolling identity.require_auth()
Liquidation liquidate, slash, slash_bond, collect_fees admin.require_auth() + stored-admin check

Because the contracts already enforce the required authorization, this change
preserves public behavior and adds focused regression coverage that proves
the invariant at the actual integration boundary
— the missing guarantee the
issue asks for.

What changed

  • New contracts/credence_bond/src/test_lifecycle_auth.rs — a
    self-contained authorization-boundary matrix over the lifecycle.
  • Wired the module into contracts/credence_bond/src/lib.rs.

The tests use selective mock_auths (not mock_all_auths), so the
host-level require_auth guards are genuinely exercised rather than bypassed.
For each lifecycle phase, coverage includes:

  • Allowed — the owning identity (or admin) can perform the operation.
  • Denied — a stranger's call is rejected.
  • Forged-identity — a stranger authorising while passing the victim's
    address as identity is rejected by require_auth.
  • Cross-tenant — one identity cannot mutate another identity's bond.
  • No-mutation — every rejected / forged / cross-tenant call leaves the
    bond, cooldown, and liquidation state unchanged (explicit equality
    assertions on IdentityBond, get_cooldown_request, and is_liquidated).

Required validation

The issue's required validation matrix is exercised by the new tests:

  • allowed / denied / forged-identity / cross-tenant cases, each with explicit
    no-mutation assertions.
  • rejected repeated/forged operations leave no unauthorized or partial state
    (e.g. a forged cooldown execution does not clear the victim's pending
    request; a forged liquidate does not set the Liquidated flag).

Commands

The workspace's host-side test infrastructure (Soroban SDK testutils) does
not compile in this environment due to a pre-existing rand_core /
ed25519-dalek version conflict in soroban-env-host (the repository's CI
test job is intentionally stubbed). This is unrelated to the change; the
change is #[cfg(test)]-only and does not affect the no_std/wasm library
build. To run the new tests once the dependency issue is resolved:

cargo test -p credence_bond test_lifecycle_auth

Compatibility

  • Public behavior is unchanged — no entry point, error, storage key, or
    response shape is modified. The change is additive (test-only).

Security assumptions

  • Authorization is enforced via Soroban's Address::require_auth, which the
    host cryptographically verifies. This module verifies that every lifecycle
    path invokes it on the correct address before any state mutation and that a
    failure never leaks partial/unauthorized state.

Operational limitations

  • Liquidation (admin-gated) and exit/cooldown tests use phantom-balance mode
    (no configured token) to keep the authorization invariant in focus; token
    custody behavior is covered by separate integration suites.



Prove, at the integration boundary, that every state-mutating bond
lifecycle path (create_bond, top_up, cooldown request/execute, withdraw,
withdraw_early, liquidate) enforces require_auth on the correct identity
or admin before any state change.

Unlike the happy-path suites (mock_all_auths), these tests use selective
mock_auths so the host-level require_auth guards are genuinely exercised
for allowed, denied, forged-identity, and cross-tenant calls, and assert
explicit no-mutation guarantees for every rejected operation.
@drips-wave

drips-wave Bot commented Aug 28, 2026

Copy link
Copy Markdown

@olacodes-01 Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@Baskarayelu
Baskarayelu merged commit d0139cf into CredenceOrg:main Aug 29, 2026
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.

[Quality][High] bond lifecycle: authorization boundaries — QE-2026-08

3 participants