Skip to content

fix(backend): correct stroop units in loan request, score breakdown, dispute and deposit paths - #2208

Merged
K1NGD4VID merged 1 commit into
LabsCrypt:mainfrom
alagbesadat208-prog:fix/backend-2019-2022
Oct 28, 2026
Merged

K1NGD4VID merged 1 commit into
LabsCrypt:mainfrom
alagbesadat208-prog:fix/backend-2019-2022

Conversation

@alagbesadat208-prog

Copy link
Copy Markdown
Contributor

Summary

Four backend fixes, one per issue. All changes are covered by tests.

#2019 — requestLoan compared tokens against stroops

req.body.amount is in human-readable token units, while sorobanService.getPoolBalance() returns raw stroops (10^7 per token). The pre-flight check compared the two numbers directly, so it was off by 10^7.

  • Compare toStroops(amount.toString()) against the balance in stroops.
  • Report both sides in token units in the error message (formatted through money/decimal.ts, trailing settlement zeros trimmed).

#2021 — getScoreBreakdown returned an empty breakdown for users without a scores row

current_score_cte had no aggregate, so it produced 0 rows for users with loan activity in contract_events but no scores row. The CROSS JOINs then discarded every computed loan_stats/timing_stats value.

  • Use COALESCE(MAX(current_score), 500) so the CTE always yields exactly one row.
  • updateScore already invalidates score:breakdown:${userId} — confirmed, no change needed.

#2020 — contestDefault wrote an invalid event outside a transaction

  • Wrapped the loan_disputes insert and the contract_events marker in one withTransaction, so a failed event insert no longer leaves an orphaned dispute row.
  • Filled every NOT NULL column on contract_events: event_id (randomUUID()), ledger: 0, tx_hash: dispute:<disputeId>, contract_id from LOAN_MANAGER_CONTRACT_ID (fallback offchain_dispute), matching the admin dispute endpoints.

#2022 — buildDepositTx left minSharesOut unscaled and the schema dropped it

  • Scale minSharesOut with toStroops(minSharesOut.toString()) before encoding it as i128, so the slippage bound is no longer 10^7 times too small (and fractional values no longer throw RangeError).
  • Added minSharesOut: z.number().nonnegative().optional() to buildPoolTransactionSchema.

Tests

  • sorobanService.stroops.test.ts: asserts minSharesOut (integer and fractional) is scaled to stroops.
  • loanEndpoints.test.ts: pool-liquidity pre-flight accepts/rejects in token units and formats the shortfall in tokens.
  • scoreBreakdown.test.ts: asserts the score CTE is aggregated so event stats survive.
  • loanDispute.test.ts / integration/loanDisputeFlow.test.ts: run through withTransaction and assert the dispute event supplies event_id, ledger, tx_hash and contract_id.
  • validation.test.ts: minSharesOut is accepted, optional, and rejects negatives.

npm run typecheck passes, eslint reports no errors on the touched files, and the full backend suite passes (124 suites, 1066 tests; 4 suites skipped).

Closes #2019
Closes #2020
Closes #2021
Closes #2022

@github-actions github-actions Bot added the security:malware-suspected Automated malware indicator found in a pull request label Oct 28, 2026
@github-actions

Copy link
Copy Markdown

Malware detection scan flagged this pull request

The scan found 1 indicator(s) in the PR diff. This PR is blocked until a maintainer reviews the flagged files.

  • backend/src/services/__tests__/sorobanService.stroops.test.ts — hidden-appended-config-payload (high)

This is an automated triage signal; maintainers must verify whether the finding is malicious or intentional.

…paths

Requesting a loan compared a human-readable token amount against a pool balance
in stroops, the score breakdown dropped every computed statistic for users
without a scores row, contesting a default wrote an invalid event outside a
transaction, and deposit slippage bounds skipped the 10^7 scaling. Compare in
stroops, aggregate the score CTE, write the dispute and its event atomically
with the NOT NULL columns filled, and scale minSharesOut through the money
policy with schema coverage.

Closes LabsCrypt#2019
Closes LabsCrypt#2020
Closes LabsCrypt#2021
Closes LabsCrypt#2022

🤖 Generated with Codebuff
Co-Authored-By: Codebuff <noreply@codebuff.com>
@K1NGD4VID
K1NGD4VID merged commit e51d3bc into LabsCrypt:main Oct 28, 2026
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment