Skip to content

fix(escrow): correct paisa-to-MATIC conversion — remove 10,000x magnitude error#621

Merged
KanishJebaMathewM merged 3 commits into
KanishJebaMathewM:mainfrom
nyxsky404:fix/606-escrow-paisa-to-matic-conversion
Jun 19, 2026
Merged

fix(escrow): correct paisa-to-MATIC conversion — remove 10,000x magnitude error#621
KanishJebaMathewM merged 3 commits into
KanishJebaMathewM:mainfrom
nyxsky404:fix/606-escrow-paisa-to-matic-conversion

Conversation

@nyxsky404

@nyxsky404 nyxsky404 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Closes #606

What was broken

bid_amount is stored in paisa (1 INR = 100 paisa, documented in lib/pricing.js). The accept-bid handler was doing:

const amountWei = ethers.parseEther((bid.bid_amount / 100).toFixed(2).toString());

bid_amount / 100 converts paisa to INR. Then ethers.parseEther(INR_value) treats that number as MATIC. A ₹5,000 bid (bid_amount=500000) would lock 5,000 MATIC (~$2,000) on-chain for a $60 order.

Fix

Replaced with a configurable ESCROW_MATIC_PER_PAISA env var that holds the explicit INR→MATIC exchange rate at the paisa granularity. If the var is not set the deposit is skipped with a warning (same existing behaviour as a missing wallet address). A MAX_ESCROW_MATIC cap rejects any deposit above the configured ceiling before it reaches the chain.

Both variables are documented in .env.example.

Summary by CodeRabbit

  • New Features

    • Added configurable on-chain escrow deposit support for MATIC, including an environment-defined conversion rate and a maximum deposit cap. Leaving the conversion rate unset disables on-chain escrow deposits.
  • Bug Fixes

    • Updated escrow deposit calculation during bid acceptance to use the configured conversion rate instead of a fixed formula.
    • Added validation for the maximum allowed MATIC amount, rejecting requests that exceed the cap and only proceeding to escrow transaction creation when inputs are valid.

…_PAISA env var

bid_amount is stored in paisa (1 INR = 100 paisa). The previous code did
bid_amount / 100 to get INR, then passed that number directly to
ethers.parseEther() as if it were an ETH/MATIC value — a 10,000x magnitude
error on every funded order.

Replace with a configurable ESCROW_MATIC_PER_PAISA rate. If the env var is
not set, the deposit is skipped with a warning (same behaviour as a missing
wallet address). A MAX_ESCROW_MATIC safety cap rejects any deposit that
exceeds the configured ceiling before it hits the chain.

Document both variables in .env.example.
Copilot AI review requested due to automatic review settings June 18, 2026 15:57
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

The escrow deposit logic in the bid-acceptance route is updated to compute the on-chain MATIC amount using a configurable ESCROW_MATIC_PER_PAISA environment variable and enforce a MAX_ESCROW_MATIC safety cap. When the rate is missing, invalid, or non-positive, the deposit is skipped with a warning logged. The computed MATIC amount is validated against the cap before conversion to Wei and transaction building.

Changes

Escrow Deposit Amount Fix and Config

Layer / File(s) Summary
Escrow env var documentation
backend/api/.env.example
Adds a new Escrow section documenting ESCROW_MATIC_PER_PAISA (paisa-to-MATIC conversion rate; leaving unset disables escrow) and MAX_ESCROW_MATIC (deposit safety cap).
Escrow amount computation, cap enforcement, and order update
backend/api/src/routes/orderRoutes.js
Parses ESCROW_MATIC_PER_PAISA and skips deposit with warning if unset/invalid/non-positive. Otherwise computes MATIC amount as bid.bid_amount × MATIC_PER_PAISA, enforces MAX_ESCROW_MATIC cap (returns 400 if exceeded), converts to Wei via ethers.parseEther, calls buildDepositTx, and updates order with escrow_booking_id and escrow_status='funding'.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Possibly related PRs

  • KanishJebaMathewM/Truxify#559: Both PRs modify the bid-acceptance escrow deposit logic in backend/api/src/routes/orderRoutes.js — this PR changes amount computation and validation, while #559 reorders escrow deposit before accept_bid_tx and adds refund compensation on later failures.
  • KanishJebaMathewM/Truxify#604: Both PRs modify the bid-acceptance escrow deposit flow in orderRoutes.js — this PR changes how MATIC amount is computed and capped, while #604 adds wallet-address preconditions before escrow validation.
  • KanishJebaMathewM/Truxify#616: Both PRs modify the accept_bid route's escrow funding phase — this PR changes how deposit amount is derived and validated via env vars, while #616 changes the flow to return customer-signed deposit data via buildDepositTx.

Suggested labels

backend, blockchain, type:bug

Poem

🐰 No more draining wallets dry,
The MATIC math now soars up high!
A paisa finds its rightful rate,
A safety cap stands guard at gate.
Hop hop — the escrow's set just right! 🌟

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly addresses the main change: fixing a 10,000x magnitude error in paisa-to-MATIC conversion, which is the core issue resolved by this PR.
Linked Issues check ✅ Passed All coding objectives from issue #606 are met: the PR implements the configurable ESCROW_MATIC_PER_PAISA exchange rate (Option A), adds MAX_ESCROW_MATIC safety cap, documents both variables, and handles missing/invalid configuration with appropriate warnings.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing the escrow conversion bug: environment configuration documentation and the accept-bid route's escrow logic. No unrelated modifications are present.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown
Contributor

🎉 Thank you for your contribution! Your pull request has been received and will be reviewed shortly.

If you enjoy the project, please consider giving the repository a ⭐. You can also follow my GitHub profile to stay updated on future open-source projects.

Thanks for being part of the community! 🚀

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
backend/api/src/routes/orderRoutes.js (1)

672-697: 🏗️ Heavy lift

Add regression tests for the new escrow conversion and failure paths.

This block changes critical money-flow behavior. Please add route-level tests for: (1) missing/invalid ESCROW_MATIC_PER_PAISA skip path, (2) cap breach 400 path, and (3) escrowDeposit returning no txHash -> 500 path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/api/src/routes/orderRoutes.js` around lines 672 - 697, Add
route-level regression tests for the escrow deposit logic to cover the three
critical paths: first, test the scenario where ESCROW_MATIC_PER_PAISA is missing
or invalid to verify the skip path with logger.warn is triggered; second, test
the scenario where the computed maticAmount exceeds maxEscrowMatic to verify a
400 status response is returned; third, test the scenario where the
escrowDeposit function completes successfully with a txHash to verify
escrowTxHash is captured, and test when escrowDeposit returns without a txHash
to verify a 500 status response is returned. These tests should use mocked
environment variables and the escrowDeposit function to validate the money-flow
behavior changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/api/.env.example`:
- Around line 42-43: The ESCROW_MATIC_PER_PAISA configuration in the
.env.example file is set to a real live exchange rate value (0.000004), which
contradicts the comment on the previous line stating that leaving it unset
disables escrow deposits. When teams copy this example file as-is, escrow
deposits will be enabled with a potentially stale rate. Remove or comment out
the value for ESCROW_MATIC_PER_PAISA on line 43 to leave it unset by default,
ensuring teams that use the example configuration will have deposits disabled
until they explicitly set a current exchange rate.

In `@backend/api/src/routes/orderRoutes.js`:
- Around line 677-680: The parseFloat call on MAX_ESCROW_MATIC environment
variable is not validated, so if the env value is invalid or non-numeric, it
will parse to NaN. When NaN is compared with maticAmount in the safety check,
the comparison always evaluates to false, disabling the safety cap. After
assigning maxEscrowMatic on line 677, add validation to check if the parsed
value is NaN using Number.isNaN() or by checking isFinite(), and either use a
safe default fallback value or handle the invalid configuration appropriately
before proceeding to the comparison check on line 678.

---

Nitpick comments:
In `@backend/api/src/routes/orderRoutes.js`:
- Around line 672-697: Add route-level regression tests for the escrow deposit
logic to cover the three critical paths: first, test the scenario where
ESCROW_MATIC_PER_PAISA is missing or invalid to verify the skip path with
logger.warn is triggered; second, test the scenario where the computed
maticAmount exceeds maxEscrowMatic to verify a 400 status response is returned;
third, test the scenario where the escrowDeposit function completes successfully
with a txHash to verify escrowTxHash is captured, and test when escrowDeposit
returns without a txHash to verify a 500 status response is returned. These
tests should use mocked environment variables and the escrowDeposit function to
validate the money-flow behavior changes.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 13ba4c04-732f-432d-8dac-027958903c2e

📥 Commits

Reviewing files that changed from the base of the PR and between 4656ed1 and d9d3fc1.

📒 Files selected for processing (2)
  • backend/api/.env.example
  • backend/api/src/routes/orderRoutes.js

Comment thread backend/api/.env.example Outdated
Comment thread backend/api/src/routes/orderRoutes.js Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes escrow deposit amount calculation during bid acceptance by replacing the incorrect paisa→INR→parseEther() flow (which treated INR as MATIC) with an explicit, configurable paisa→MATIC exchange rate and a hard safety cap, and documents the new configuration.

Changes:

  • Update bid-accept escrow funding to use ESCROW_MATIC_PER_PAISA (paisa-granularity exchange rate) instead of (bid_amount/100) interpreted as MATIC.
  • Add MAX_ESCROW_MATIC guardrail to reject deposits above a configured ceiling before sending an on-chain transaction.
  • Document escrow configuration in backend/api/.env.example.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
backend/api/src/routes/orderRoutes.js Reworks escrow deposit amount computation to be exchange-rate driven and adds a max-cap check plus improved failure handling.
backend/api/.env.example Documents ESCROW_MATIC_PER_PAISA and MAX_ESCROW_MATIC and provides an example configuration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread backend/api/src/routes/orderRoutes.js
…nv.example

NaN from a misconfigured MAX_ESCROW_MATIC would make the cap comparison
always false, silently disabling the safety check. Now explicitly validate
the parsed value and fail closed with 500 if it is invalid.

Clear the ESCROW_MATIC_PER_PAISA default value in .env.example — shipping a
concrete exchange rate causes teams that copy the file as-is to enable
live deposits with a potentially stale rate, contradicting the adjacent
comment that leaving it unset disables escrow.
@nyxsky404

Copy link
Copy Markdown
Contributor Author

CI failures are pre-existing — backend test failures (expected 500, got 422) exist on main before this PR due to the wallet-address 422 guard firing before the RPC call in those test setups. Flutter failures are unrelated to this change.

# Conflicts:
#	backend/api/src/routes/orderRoutes.js
@KanishJebaMathewM KanishJebaMathewM merged commit 4bb998b into KanishJebaMathewM:main Jun 19, 2026
5 of 7 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

🎉 Thank you for your contribution!

Your pull request has been merged successfully. We appreciate your work and look forward to your future contributions. 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Escrow deposit converts bid_amount paisa to ETH directly — 10,000x magnitude error on every funded order

3 participants