[RELEASE] fix batched USDC transactions - #623
Conversation
Markup for x402 and batched fundRepo event
|
🚅 Deployed to the echo-pr-623 environment in echo
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
Co-authored-by: vercel[bot] <35613825+vercel[bot]@users.noreply.github.com>
| const transactionCostWithMarkup = applyMaxCostMarkup(transaction.rawTransactionCost); | ||
|
|
||
| // rawTransactionCost is what we pay to OpenAI | ||
| // transactionCostWithMarkup is what we charge the user | ||
| // markup is the difference between the two, and is sent with fundRepo (not every time, just when it is worthwhile to send a payment) | ||
|
|
||
| // The user should be refunded paymentAmountDecimal - transactionCostWithMarkup\ | ||
|
|
||
|
|
||
| const refundAmount = calculateRefundAmount( | ||
| paymentAmountDecimal, | ||
| transaction.rawTransactionCost | ||
| transactionCostWithMarkup | ||
| ); |
There was a problem hiding this comment.
| const transactionCostWithMarkup = applyMaxCostMarkup(transaction.rawTransactionCost); | |
| // rawTransactionCost is what we pay to OpenAI | |
| // transactionCostWithMarkup is what we charge the user | |
| // markup is the difference between the two, and is sent with fundRepo (not every time, just when it is worthwhile to send a payment) | |
| // The user should be refunded paymentAmountDecimal - transactionCostWithMarkup\ | |
| const refundAmount = calculateRefundAmount( | |
| paymentAmountDecimal, | |
| transaction.rawTransactionCost | |
| transactionCostWithMarkup | |
| ); | |
| // The user was charged maxCostWithMarkup (applied in server.ts) | |
| // They should only pay the actual transaction cost (rawTransactionCost) | |
| // So refund = paymentAmount - actualCost (no additional markup needed) | |
| const refundAmount = calculateRefundAmount( | |
| paymentAmountDecimal, | |
| transaction.rawTransactionCost | |
| ); | |
| // Calculate markup for profit tracking (but don't apply it to refund calculation) | |
| const transactionCostWithMarkup = applyMaxCostMarkup(transaction.rawTransactionCost); |
The refund calculation incorrectly applies markup to the actual transaction cost, causing users to be overcharged when the actual cost is lower than the estimated maximum cost.
View Details
Analysis
Double markup application in finalize() causes user overcharges
What fails: finalize() function in /packages/app/server/src/handlers.ts applies markup twice - once to estimate (server.ts:111) then again to actual cost (handlers.ts:121), causing users to pay more than actual transaction cost + intended markup
How to reproduce:
// Scenario: Estimated cost 100 USD, actual cost 50 USD, markup 1.25x
// User charged: 125 USD (100 * 1.25)
// Buggy refund: 125 - (50 * 1.25) = 62.5 USD
// User pays: 62.5 USD instead of 50 USD (12.5 USD overcharge)Result: Users systematically overcharged when actual costs are below estimates. In test case: 12.5 USD overcharge (25% of actual cost).
Expected: Refund should be paymentAmount - rawTransactionCost so users pay exactly the actual cost, with markup profit tracked separately for fundRepo operations.
There was a problem hiding this comment.
this is actually correct. The user should be refunded paymentAmountDecimal - transactionCostWithMarkup.
The final cost to the user should be raw tx cost + markup amount.
Add xAI Grok model support
Add Documentation for Echo Shadcn Components Registry
|
|
||
| export function applyMaxCostMarkup(maxCost: Decimal): Decimal { | ||
| const markup = process.env.MAX_COST_MARKUP || '1.25'; | ||
| return maxCost.mul(new Decimal(markup)); |
There was a problem hiding this comment.
| return maxCost.mul(new Decimal(markup)); | |
| try { | |
| const markupDecimal = new Decimal(markup); | |
| if (!markupDecimal.isFinite() || markupDecimal.isNaN()) { | |
| throw new Error('Invalid markup value - not a finite number'); | |
| } | |
| return maxCost.mul(markupDecimal); | |
| } catch (error) { | |
| // Log the error and fall back to default markup | |
| console.error(`Invalid MAX_COST_MARKUP value "${markup}": ${error instanceof Error ? error.message : 'Unknown error'}. Using default markup 1.25.`); | |
| return maxCost.mul(new Decimal('1.25')); | |
| } |
The applyMaxCostMarkup function passes the MAX_COST_MARKUP environment variable directly to the Decimal constructor without validating it's a valid number. If an invalid value is set, the application will crash when processing requests.
View Details
Analysis
Invalid MAX_COST_MARKUP environment variable crashes server
What fails: applyMaxCostMarkup() in packages/app/server/src/services/PricingService.ts passes process.env.MAX_COST_MARKUP directly to new Decimal() without validation, causing application crashes when the environment variable contains invalid values
How to reproduce:
# Set invalid environment variable and make a request:
MAX_COST_MARKUP="invalid" node -e "
const { applyMaxCostMarkup } = require('./dist/server.js');
const { Decimal } = require('@prisma/client/runtime/library');
applyMaxCostMarkup(new Decimal('100'));
"Result: [DecimalError] Invalid argument: invalid exception crashes the server. Function is called in critical request paths in server.ts:111 and handlers.ts:121 without error handling.
Expected: Application should handle invalid environment variables gracefully and continue serving requests with fallback values.
Fix: Added try-catch validation in applyMaxCostMarkup() that validates the Decimal construction and falls back to default markup (1.25) when invalid values are encountered, with error logging for visibility.
feat: better local development environment
version bump errting
ETH_ADDRESS
ETH_WARNING_THRESHOLD
BASE_USDC_TRANSFER_THRESHOLD
MAX_COST_MARKUP
Should be added to the env var