Skip to content

BountiesService.markMergedAndRelease marks a team-assigned bounty PAID even when team.splits is empty, skipping the payout entirely #102

Description

@chonilius

In src/bounties/bounties.service.ts, markMergedAndRelease's team branch is:

if (team && team.splits.length > 0) {
  ...
  await this.escrowService.splitRelease(bounty.escrowId, recipients);
}

If team.splits.length === 0, this branch is silently skipped — no splitRelease call happens, no Payment rows are created, the escrow is never touched. Execution falls straight through to:

assertTransition(bounty.status, BountyStatus.PAID);
bounty.status = BountyStatus.PAID;
bounty.paidAt = new Date();
return this.bountyRepo.save(bounty);

The bounty is marked PAID regardless, with paidAt stamped, even though zero dollars were released and the escrow is still sitting LOCKED.

A team can legitimately reach zero splits via the CASCADE-on-user-delete path #58 already documents (every member of a team's account gets deleted, cascading their TeamMemberSplit rows away). Once that happens, any bounty assigned to that team that later merges will silently record itself as fully paid without paying anyone — the exact opposite of #46's "stuck and unpayable" failure mode; this one actively falsifies the ledger.

Fix: when team.splits.length === 0, throw rather than silently falling through to the PAID transition — there is no recipient to pay, so the bounty shouldn't advance past MERGED until the team is repaired or reassigned.

Metadata

Metadata

Assignees

Labels

Stellar WaveIssues in the Stellar wave programarchitectureArchitecture/design issuebugSomething isn't workinghelp wantedExtra attention is neededspikeOpen-ended research/investigation task

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions