Skip to content

fix: add storage non-mutation coverage to multisig_approval_init guar… - #425

Open
Yerimahjr wants to merge 1 commit into
Goldii-locks:mainfrom
Yerimahjr:fix/353-harden-multisig-approval-init-guards
Open

fix: add storage non-mutation coverage to multisig_approval_init guar…#425
Yerimahjr wants to merge 1 commit into
Goldii-locks:mainfrom
Yerimahjr:fix/353-harden-multisig-approval-init-guards

Conversation

@Yerimahjr

Copy link
Copy Markdown

Closes #353

Summary

multisig_approval_init's authorization (require_admin) and precondition
(AlreadyInitialized) guards were already correctly implemented and ordered
before any storage read/write — verified by comparing against this repo's
own established pattern for this exact class of issue (prior closed
harden caller authorization and precondition guards in <function> issues
for admin_override_cancel_release and multisig_split_refund).

What was missing, per the issue's own acceptance criteria — "that no storage
entry is mutated in either case" — was test coverage proving it.

Changes

contracts/milestone-escrow/src/test.rs

Strengthened the two existing guard tests to additionally assert no storage
mutation on rejection:

  • test_multisig_approval_init_unauthorized_fails
  • test_multisig_approval_init_duplicate_fails (the "illegal source state"
    case — a second call to this one-time-init function)

Each now also confirms, after the expected typed error:

  1. is_multisig_approved(0).threshold is still the original value, not the
    attacker's attempted one.
  2. The attacker/impostor's address was never written into the signer set —
    confirmed by calling multisig_approve as them and getting Unauthorized.

contracts/milestone-escrow/src/admin_override_cancel_tests.rs

Unrelated pre-existing bug, fixed so the crate's test suite can compile and
run at all: this file (added by a separately-merged PR closing #383/#386)
was missing #![cfg(test)] — every other test module in this crate has it —
so it compiled unconditionally instead of only under cfg(test), making
soroban_sdk::testutils::Address::generate unavailable and the sibling
test module's setup_funded_escrow helper inaccessible. Added the missing
gate, the missing testutils::Address as _ import, and made
setup_funded_escrow pub(crate).

Test results

running 463 tests
test result: FAILED. 454 passed; 9 failed

The 454 passed include both target tests for this issue, and every other
test in the crate — this is effectively the crate's first-ever successful
compile+run, since it could not build before this branch. The 9 failures
are all pre-existing, in admin_override_cancel_tests::test_cancel_refund_*
(testing admin_override_cancel_refund, issue #386 — a different function
entirely), never having run before now. Root cause: admin_override_cancel_refund
calls admin.require_auth() redundantly before require_admin (which
already does so internally) — the same bug already fixed in the sibling
admin_override_cancel_release, just missed here. Flagging as a separate
issue rather than bundling an unrelated fix into this PR.

cargo fmt --check: not re-verified after this session's edits — please
confirm in CI.

Note on contracts/reports

This repo also contains a duplicate multisig_approval_init implementation
in contracts/reports/src/lib.rs, which has the same guards already correct.
However, contracts/reports is not a member of the workspace (Cargo.toml
workspace.members only lists contracts/milestone-escrow, and always has,
since the very first commit), and its package is literally named
milestone-escrow internally — a name collision that blocks simply adding
it as a workspace member. It cannot currently be built or tested at all, so
no changes were made there. Flagging for maintainers to decide whether it
should be wired into the workspace (under a different name) or removed.

…d tests (Goldii-locks#353)

Also fixes an unrelated pre-existing compile break in
admin_override_cancel_tests.rs (missing #![cfg(test)] gate and
inaccessible setup_funded_escrow helper) so the crate's test suite
can build and run at all.
@drips-wave

drips-wave Bot commented Aug 29, 2026

Copy link
Copy Markdown

@Yerimahjr 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

@Yerimahjr

Copy link
Copy Markdown
Author

Please review and merge

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.

Harden caller authorization and precondition guards in multisig_approval_init

1 participant