Skip to content

fix(atomic_swap): pay insurance claims from per-policy reservations - #936

Merged
fejilaup-cloud merged 1 commit into
AtomicIP:mainfrom
DevMusa001:fix/insurance-coverage-reservation-354
Aug 28, 2026
Merged

fix(atomic_swap): pay insurance claims from per-policy reservations#936
fejilaup-cloud merged 1 commit into
AtomicIP:mainfrom
DevMusa001:fix/insurance-coverage-reservation-354

Conversation

@DevMusa001

Copy link
Copy Markdown
Contributor

PR Summary

Pay insurance claims from per-policy reservations

Problem

claim_insurance computed actual_payout = if pool >= payout { payout } else { pool }, paying every policy from one fungible InsurancePool(token) balance. Two valid policies on the same token could be claimed in sequence, and the second claimant silently got a partial payout or zero, with no error separating "your claim is invalid" from "someone drained the pool first".

Fix

  • New keys InsuranceReserved(swap_id) and InsuranceReservedTotal(token), kept as DataKey variants rather than SwapRecord fields so existing test literals compile untouched.
  • A reservation equal to the coverage amount is carved wherever the premium is collected: accept_swap and batch_accept_swaps.
  • claim_insurance pays that policy's own reservation or panics. It never transfers a reduced amount.
  • Release is centralized in save_swap instead of duplicated across ~20 status transitions, and is skipped while a swap is still flagged InsuranceClaimable.

New errors

Error Code Meaning
InsuranceNotReserved 66 Policy holds no reservation
InsufficientInsuranceReserve 67 Claim valid, pool under-collateralized, nothing transferred

New API

  • get_insurance_pool_status(token) returns InsurancePoolStatus { token, balance, reserved, collateralized, shortfall }, so under-collateralization is observable before it causes a failed payout.
  • get_insurance_reservation(swap_id).
  • fund_insurance_pool(funder, token, amount). Not in the original scope but load-bearing: a policy contributes 2% of price and reserves 100% of it, so a premium-only pool is under-collateralized by construction and every claim would panic #67.

Tests

Five tests in insurance_reserve_tests, all issuing policies through the real initiate_swap then accept_swap path:

  • Two policies both paid in full, A then B and B then A.
  • Claim against an under-collateralized pool panics #67.
  • Claim with no reservation panics #66.
  • Shortfall visible via get_insurance_pool_status before any claim.

cargo build --workspace and cargo test --workspace are green, including the Redis-gated api-server tests.

Unchanged

Premium calculation, risk-factor, and tiering logic are untouched. The premium stays 2% of price in both initiate_swap and batch_initiate_with_insurance.

Known issue not fixed here

reveal_key sets InsuranceClaimable(swap_id) and then calls panic_with_error(InvalidKey), which reverts the write, so the flag cannot persist and claim_insurance is unreachable through that path. Pre-existing, and fixing it changes reveal_key's revert semantics. Tests seed the flag directly.

Closes

Closes #789

@fejilaup-cloud
fejilaup-cloud merged commit bdcc975 into AtomicIP:main Aug 28, 2026
1 check passed
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.

Insurance claim payouts race against a shared pool with no per-policy reservation

2 participants