Skip to content

Commit 0954f71

Browse files
authored
fix(predict): cap slippage to avoid sharePrice > 1 (MetaMask#22354)
## **Description** This PR fixes a bug in the Polymarket prediction provider where orders could fail due to an invalid share price calculation. The issue occurred when slippage was applied to `minAmountReceived`, causing the calculated share price to exceed 1 (which is mathematically impossible for prediction market shares). The fix introduces a cap on `minAmountWithSlippage` to ensure it never falls below `maxAmountSpent + tickSize`, preventing the share price from exceeding 1 while still accounting for slippage to reduce order failure rates. ## **Changelog** CHANGELOG entry: null ## **Related issues** Fixes: ## **Manual testing steps** ```gherkin Feature: Polymarket prediction order execution Scenario: user creates a prediction market order with slippage Given the user is on the Predict feature And a Polymarket prediction market is available When user creates an order with slippage applied Then the order should execute successfully without sharePrice > 1 errors And the minAmountReceived should be capped appropriately ``` ## **Screenshots/Recordings** <!-- If applicable, add screenshots and/or recordings to visualize the before and after of your change. --> ### **Before** <!-- Orders could fail with sharePrice > 1 errors --> ### **After** <!-- Orders execute successfully with proper slippage capping --> ## **Pre-merge author checklist** - [x] I've followed [MetaMask Contributor Docs](https://github.com/MetaMask/contributor-docs) and [MetaMask Mobile Coding Standards](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/CODING_GUIDELINES.md). - [x] I've completed the PR template to the best of my ability - [x] I've included tests if applicable - [x] I've documented my code using [JSDoc](https://jsdoc.app/) format if applicable - [x] I've applied the right labels on the PR (see [labeling guidelines](https://github.com/MetaMask/metamask-mobile/blob/main/.github/guidelines/LABELING_GUIDELINES.md)). Not required for external contributors. ## **Pre-merge reviewer checklist** - [ ] I've manually tested the PR (e.g. pull and build branch, run the app, test code being changed). - [ ] I confirm that this PR addresses all acceptance criteria described in the ticket it closes and includes the necessary testing evidence such as recordings and or screenshots. <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Adjusts slippage handling in `PolymarketProvider.placeOrder` by flooring BUY `minAmountWithSlippage` at `maxAmountSpent + tickSize` before rounding to avoid invalid share prices. > > - **Predict/Polymarket**: > - Update `placeOrder` slippage logic: > - Compute `_minWithSlippage = minAmountReceived * (1 - slippage)`. > - For `BUY`, floor to `maxAmountSpent + tickSize` before rounding via `roundOrderAmount`. > - Use the rounded value to derive `takerAmount`. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit dc8a157. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent dddee92 commit 0954f71

1 file changed

Lines changed: 18 additions & 2 deletions

File tree

app/components/UI/Predict/providers/polymarket/PolymarketProvider.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -588,11 +588,27 @@ export class PolymarketProvider implements PredictProvider {
588588
throw new Error('Maker address not found');
589589
}
590590

591-
// Introduce slippage into minAmountReceived to reduce failure rate
591+
/*
592+
* Introduce slippage into minAmountReceived to reduce failure rate.
593+
*/
592594
const roundConfig = ROUNDING_CONFIG[tickSize.toString() as TickSize];
593595
const decimals = roundConfig.amount ?? 4;
596+
597+
let _minWithSlippage = minAmountReceived * (1 - slippage);
598+
/*
599+
* For BUY orders, the minAmountWithSlippage needs to be capped at
600+
* maxAmountSpent + tickSize, otherwise, the order will fail due to
601+
* sharePrice being >= 1 (which is impossible).
602+
*/
603+
if (side === Side.BUY) {
604+
_minWithSlippage = Math.max(
605+
_minWithSlippage,
606+
maxAmountSpent + tickSize,
607+
);
608+
}
609+
594610
const minAmountWithSlippage = roundOrderAmount({
595-
amount: minAmountReceived * (1 - slippage),
611+
amount: _minWithSlippage,
596612
decimals,
597613
});
598614

0 commit comments

Comments
 (0)