Skip to content

Recipient Deduplication Guard #556

Description

@Kingsman-99

Description

If the same Address appears more than once in the recipients list supplied at invoice creation, the contract silently assigns it multiple shares, resulting in double (or triple) payout to that address and a corresponding deficit for others. The contract must reject any initialize() call where the recipient list contains duplicate addresses before any storage is written.

Technical Context

contracts/split/src/lib.rsinitialize() entry point, which currently iterates recipients: Vec<RecipientShare> without uniqueness enforcement; contracts/split/src/validation.rs — add assert_unique_recipients(env: &Env, recipients: &[RecipientShare]) using a soroban_sdk::Map<Address, bool> for O(n log n) membership tracking; contracts/split/src/error.rs — add Error::DuplicateRecipient variant; the existing split_ratio_sum_validation logic in the same file serves as a structural reference for chaining validation guards.

Acceptance Criteria

  • initialize() calls assert_unique_recipients() before writing any DataKey entry and returns Error::DuplicateRecipient on the first duplicate found
  • The error code is distinct from all other Error variants and is documented in contracts/split/src/error.rs
  • A test in contracts/split/src/tests/validation_tests.rs verifies that a recipient list with two identical addresses is rejected at the correct call site
  • A test verifies that a list where all addresses are distinct passes the deduplication check and proceeds to storage write
  • The check uses no unbounded heap allocation and completes in a single pass over the recipient slice
  • All CI checks (cargo build --target wasm32-unknown-unknown, cargo test, cargo clippy) pass and the branch has no merge conflicts

Metadata

Metadata

Labels

Stellar WaveIssues in the Stellar wave programcomplexity: highComplex feature requiring deep knowledge - 200 ptssecuritySecurity hardening and access control

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions