Skip to content

Close the Zero-Coverage Gap Around the Two-Phase Settlement Commit/Abort Protocol #1829

Description

@Emmyt24

Description

contracts/governance/src/settlement.rs implements the cross-contract two-phase prepare_settlementcommit_settlement (with abort_settlement fallback) protocol that execute_proposal relies on for treasury disbursements, but a full-text search confirms zero references to disbursement, settlement, or token_factory anywhere in contracts/governance/src/governance_test.rs, governance_property_test.rs, or governance_bounds_test.rs. Neither the happy path (successful commit) nor the abort path (commit fails, abort_settlement is invoked and FinalizationError::DisbursementFailed is returned) has any unit test coverage, despite this being one of the contract's most structurally complex code paths.

Requirements and Context

  • Must not modify settlement::execute_disbursement's cross-contract call sequence (prepare_settlementcommit_settlement → conditional abort_settlement); this is test-only work.
  • Since settlement.rs's own module doc explains governance and token-factory pin different soroban-sdk major versions and therefore cannot share a generated client, the test double must be a minimal in-crate mock contract registered via env.register_contract, not a real token-factory dependency.
  • New tests must be deterministic and not depend on any external .wasm artifact (unlike the fuzz target in token-factory/fuzz, which does depend on a pre-built governance.wasm).

Suggested Execution

Branch: test/governance-settlement-coverage

Implement Changes

  • Add a small mock contract (in a new contracts/governance/src/settlement_test.rs, gated #[cfg(test)]) exposing prepare_settlement, commit_settlement, and abort_settlement entry points with controllable success/failure behavior, matching the symbol names settlement.rs invokes via Env::invoke_contract/try_invoke_contract.
  • Register the mock via env.register_contract in place of a real token-factory address, call set_token_factory with its ID, create and pass a proposal carrying a Disbursement, then call execute_proposal and assert ProposalStatus::Executed is set only after a successful mocked commit.
  • Add a second test where the mock's commit_settlement is configured to fail, and assert execute_proposal returns FinalizationError::DisbursementFailed, the mock's abort_settlement was invoked, and the proposal's status remains Passed (not Executed).
  • Declare the new module with #[cfg(test)] mod settlement_test; in contracts/governance/src/lib.rs.

Test and Commit

Run cargo test --lib (and cargo test for proptest/fuzz targets where relevant) in the appropriate contracts/<governance|token-factory> directory, confirming the new coverage passes and cargo build --target wasm32v1-none --release --lib still succeeds.

Example Commit Message

test(contract): cover settlement's prepare/commit/abort protocol with a mock token-factory

Closes #<issue>

Guidelines

  • Branch from main, open a PR back to main
  • All new code must have corresponding tests
  • Run cargo fmt --check, cargo clippy, and cargo test --lib before pushing
  • Follow existing naming conventions and file structure
  • PR description must reference this issue number (e.g., Closes #<issue>)
  • Keep commits atomic and use conventional commit format

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Stellar WaveIssues in the Stellar wave programcontractSoroban smart contract worktestingTesting-focused contribution

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions