Skip to content

[milestone_escrow] release_milestone() has a defensive balance check but no protection against concurrent release races #883

Description

@Wilfred007

Description

release_milestone() checks for insufficient escrow balance defensively, but there's no mechanism preventing two release calls for different milestones on the same escrow from being processed in a way that double-counts available balance. In a single-threaded Soroban execution model this may not be exploitable today, but the lack of an explicit invariant check (e.g. re-deriving available balance from storage right before transfer) makes this fragile under future contract changes (e.g. batched or cross-contract calls).

Where

contracts/milestone_escrow/src/lib.rs (~line 381-385)

Acceptance Criteria

  • Document the current concurrency model assumptions explicitly in code comments
  • Add an invariant assertion that re-derives remaining balance from milestone state before transfer
  • Add a test simulating sequential releases across milestones and asserting balances never go negative or double-spend

Metadata

Metadata

Assignees

Labels

Stellar WaveIssues in the Stellar wave programcontractSmart Contract developmenthardComplex tasks

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions