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

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