-
Notifications
You must be signed in to change notification settings - Fork 12
trading credits #399
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
trading credits #399
Conversation
✅ Deploy Preview for seer-pm ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
WalkthroughAdds SeerCredits ERC20 and CreditsManager contracts with deployments and scripts; wires Seer Credits through frontend trade flow by adding isSeerCredits/type flags, wrapping trade executions to route swaps via CreditsManager.execute, and passing explicit maxSlippage through quote and execution hooks. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant UI as Swap UI
participant Hooks as Trade Hooks
participant Utils as wrap util
participant Wallet as User Wallet
participant CM as CreditsManager (on-chain)
participant SC as SeerCredits (on-chain)
participant DEX as DEX Router
UI->>Hooks: submit trade (includes isSeerCredits, maxSlippage)
Hooks->>Utils: build underlyingExecution
alt isSeerCredits = true
Utils-->>Hooks: wrappedExecution -> target CM.execute(to, data, amount, outputToken)
Hooks->>Wallet: sendTransaction(wrappedExecution)
Wallet->>CM: tx to CM.execute(...)
CM->>SC: seerCredits.burn(user, amount)
CM->>DEX: approve token, call(to, data)
DEX-->>CM: swap result
CM->>Wallet: verify recipient received outputToken
else
Hooks->>Wallet: sendTransaction(underlyingExecution)
Wallet->>DEX: tx -> DEX router
end
Wallet-->>Hooks: tx receipt
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/src/hooks/trade/index.ts (1)
308-314: Fix missing Seer Credits wrapper in 7702 path.7702 path doesn’t wrap executions with CreditsManager; Seer Credits trades will bypass credits logic.
Apply:
- calls.push( - props.trade instanceof UniswapTrade - ? await getUniswapTradeExecution(props.trade, props.account) - : await getSwaprTradeExecution(props.trade, props.account, props.isBuyExactOutputNative, props.isSellToNative), - ); + calls.push( + getWrappedSeerCreditsExecution( + props.isSeerCredits, + props.trade, + props.trade instanceof UniswapTrade + ? await getUniswapTradeExecution(props.trade, props.account) + : await getSwaprTradeExecution(props.trade, props.account, props.isBuyExactOutputNative, props.isSellToNative), + ), + );And add import at top:
+import { getWrappedSeerCreditsExecution } from "./utils";
🧹 Nitpick comments (7)
web/src/components/Market/CollateralDropdown.tsx (2)
21-39: Add de-duplication when adding Seer Credits to options.If Seer Credits is ever part of configured collaterals, you could end up with duplicates. Guard against it when pushing.
Apply this diff:
if (type === "sell" && market.chainId in seerCreditsAddress) { - options.push(seerCreditsAddress[market.chainId as keyof typeof seerCreditsAddress]); + const sc = seerCreditsAddress[market.chainId as keyof typeof seerCreditsAddress]; + if (!options.some((a) => a.toLowerCase() === sc.toLowerCase())) { + options.push(sc); + } }
51-51: Memoize collateral options to avoid recomputation on each render.This reduces unnecessary re-renders and avoids re-running the query with identical inputs.
Apply this diff:
- const { data: collateralTokens } = useTokensInfo(getCollateralOptions(market, props.type), market.chainId); + const collateralOptions = useMemo(() => getCollateralOptions(market, props.type), [market, props.type]); + const { data: collateralTokens } = useTokensInfo(collateralOptions, market.chainId);And add the missing import at Line 10:
-import { useState } from "react"; +import { useMemo, useState } from "react";web/src/lib/config.ts (1)
7-7: Helper looks good; small type-safety polish suggestedImplementation is fine. You can avoid the in + type assertion by pulling the address once and short-circuiting.
Apply this diff:
-export function isSeerCredits(chainId: SupportedChain, tokenAddress: Address) { - return ( - chainId in seerCreditsAddress && - tokenAddress.toLowerCase() === seerCreditsAddress[chainId as keyof typeof seerCreditsAddress].toLowerCase() - ); -} +export function isSeerCredits(chainId: SupportedChain, tokenAddress: Address) { + const addr = seerCreditsAddress[chainId as keyof typeof seerCreditsAddress]; + return !!addr && tokenAddress.toLowerCase() === addr.toLowerCase(); +}Confirm seerCreditsAddress actually includes all chains you expect to support initially (e.g., gnosis/sepolia). If generation is pending, run the wagmi generate step and re-check the export.
Also applies to: 186-191
contracts/deployments/gnosis/SeerCredits.json (2)
322-338: Avoid external self-call in setCreditsBalance.Using
this.balanceOf(...)performs an external call; prefer direct mapping read for gas and simplicity.Change in SeerCredits.sol:
-uint256 currentBalance = this.balanceOf(_addresses[i]); +uint256 currentBalance = balanceOf[_addresses[i]];
440-441: Compiler optimizer disabled.
optimizer.enabledis false in metadata; enable it for production deployments to reduce gas.In Hardhat config/solc settings:
-optimizer: { enabled: false, runs: 200 } +optimizer: { enabled: true, runs: 200 }Recompile and redeploy.
web/src/hooks/trade/index.ts (2)
135-135: Align Uniswap enablement with selection logic.You enable Uniswap quotes on Base but never select them (selection only for mainnet/optimism). Remove Base from enablement to avoid wasted queries.
- Number(amount) > 0 && (chainId === mainnet.id || chainId === optimism.id || chainId === base.id) && enabled, + Number(amount) > 0 && (chainId === mainnet.id || chainId === optimism.id) && enabled,
174-184: Gate DEX quote fetching to reduce unnecessary calls.You always fetch Swapr/Uniswap quotes even when CoW is chosen or when instant swap is off/on. Gate them with
shouldUseInstantSwap.- const swaprResult = useSwaprQuote( + const swaprResult = useSwaprQuote( chainId, account, amount, outcomeToken, realCollateralToken, swapType, - true, + shouldUseInstantSwap, tradeType, maxSlippage, ); - const uniswapResult = useUniswapQuote( + const uniswapResult = useUniswapQuote( chainId, account, amount, outcomeToken, realCollateralToken, swapType, - true, + shouldUseInstantSwap, tradeType, maxSlippage, );Also applies to: 185-195
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (21)
contracts/deploy/30-deploy-credits-manager.ts(1 hunks)contracts/deployments/gnosis/CreditsManager.json(1 hunks)contracts/deployments/gnosis/SeerCredits.json(1 hunks)contracts/package.json(1 hunks)contracts/scripts/trading-credits.js(1 hunks)contracts/src/trading-credits/CreditsManager.sol(1 hunks)contracts/src/trading-credits/SeerCredits.sol(1 hunks)web/src/components/Market/CollateralDropdown.tsx(4 hunks)web/src/components/Market/SwapTokens/SwapTokensConfirmation.tsx(3 hunks)web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx(4 hunks)web/src/components/Market/SwapTokens/SwapTokensMarket.tsx(4 hunks)web/src/components/Market/SwapTokens/TokenSelector.tsx(1 hunks)web/src/hooks/trade/executeSwaprTrade.ts(2 hunks)web/src/hooks/trade/executeUniswapTrade.ts(1 hunks)web/src/hooks/trade/index.ts(6 hunks)web/src/hooks/trade/useTradeConditions.ts(1 hunks)web/src/hooks/trade/utils.ts(2 hunks)web/src/hooks/useGlobalState.ts(3 hunks)web/src/lib/config.ts(2 hunks)web/src/lib/paths.ts(2 hunks)web/wagmi.config.ts(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (13)
web/src/components/Market/SwapTokens/SwapTokensConfirmation.tsx (1)
web/src/lib/config.ts (1)
isSeerCredits(186-191)
web/src/hooks/trade/useTradeConditions.ts (1)
web/src/lib/config.ts (1)
COLLATERAL_TOKENS(39-73)
web/src/hooks/trade/utils.ts (2)
web/src/lib/config.ts (1)
isSeerCredits(186-191)web/src/hooks/useCheck7702Support.ts (1)
Execution(5-9)
web/src/hooks/trade/executeUniswapTrade.ts (2)
web/src/hooks/trade/utils.ts (1)
getWrappedSeerCreditsExecution(156-181)web/src/lib/toastify.tsx (1)
toastifyTx(133-189)
contracts/deploy/30-deploy-credits-manager.ts (1)
contracts/scripts/trading-credits.js (1)
deployer(42-42)
web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx (1)
web/src/lib/config.ts (1)
isSeerCredits(186-191)
web/src/components/Market/CollateralDropdown.tsx (2)
web/src/lib/market.ts (1)
Market(68-98)web/src/hooks/useTokenInfo.ts (1)
useTokensInfo(52-60)
web/src/hooks/trade/executeSwaprTrade.ts (2)
web/src/hooks/trade/utils.ts (1)
getWrappedSeerCreditsExecution(156-181)web/src/lib/toastify.tsx (1)
toastifyTx(133-189)
web/src/hooks/useGlobalState.ts (2)
web/src/lib/tokens.ts (1)
Token(8-13)web/src/lib/config.ts (1)
isSeerCredits(186-191)
web/src/hooks/trade/index.ts (5)
web/src/lib/chains.ts (3)
SupportedChain(30-30)mainnet(8-8)optimism(8-8)web/src/lib/tokens.ts (1)
Token(8-13)web/src/lib/config.ts (2)
isSeerCredits(186-191)COLLATERAL_TOKENS(39-73)web/src/hooks/trade/executeUniswapTrade.ts (1)
executeUniswapTrade(9-30)web/src/hooks/trade/executeSwaprTrade.ts (1)
executeSwaprTrade(12-35)
web/src/lib/paths.ts (2)
web/src/lib/config.ts (1)
isSeerCredits(186-191)web/src/lib/chains.ts (1)
SupportedChain(30-30)
web/src/components/Market/SwapTokens/SwapTokensMarket.tsx (1)
web/src/lib/config.ts (1)
isSeerCredits(186-191)
web/src/lib/config.ts (2)
web/netlify/edge-functions/utils/types.ts (1)
SupportedChain(7-7)web/src/lib/chains.ts (1)
SupportedChain(30-30)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Redirect rules - seer-pm
- GitHub Check: Header rules - seer-pm
- GitHub Check: Pages changed - seer-pm
🔇 Additional comments (9)
web/src/components/Market/SwapTokens/TokenSelector.tsx (1)
45-48: LGTM: Propagatingtypeto CollateralDropdown.web/src/hooks/trade/utils.ts (2)
6-10: LGTM: Imports for CreditsManager wrapping.
156-181: Preserve execution.value and align approval spender
- In
getWrappedSeerCreditsExecution, replace- value: 0n, + value: tradeExecution.value,- Verify that wherever you call
approveIfNeeded(or your approval flow) you passcreditsManagerAddress[trade.chainId]as thespenderwhenisSeerCreditsistrue.web/src/components/Market/CollateralDropdown.tsx (1)
18-19: All CollateralDropdown usages include the newtypeprop. No additional call sites found; no further changes required.web/src/lib/paths.ts (1)
70-72: Asset path validated: file exists atweb/public/assets/android-icon-192x192.pngand no Next.jsbasePathis configured, so returning/assets/android-icon-192x192.pngwill resolve correctly.web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx (1)
10-10: LGTM: wiring isSeerCredits import and orderType="limit" into trade conditionsBoth changes are consistent with the new trading credits flow and limit order mode.
Also applies to: 119-121
web/src/hooks/trade/executeSwaprTrade.ts (1)
25-28: LGTM: switched to toastifyTx for consistent UX and receipt handlingGood move to standardize transaction toasts and receipt polling with toastifyTx.
web/src/hooks/trade/index.ts (1)
154-161: LGTM on Seer Credits collateral handling.Replacing Seer Credits with chain primary collateral for quoting and disabling CoW when credits are used is consistent with the execution wrappers.
Please confirm that COLLATERAL_TOKENS[chainId].primary always exists for every SupportedChain exposed to the UI.
Also applies to: 166-171, 190-195
contracts/deployments/gnosis/SeerCredits.json (1)
2-2: Ensure frontend mapping for Gnosis SeerCredits is updated
The generated-trading-credits contract mapping must include an entry for the Gnosis chain with address0x3a0D8671eFcBc172eDBE32F91169BBc984dC607C. Re-run your codegen or manually updateseerCreditsAddress[gnosis]to match the deployed address.
| "hhf:gnosis": "npx hardhat node --fork https://gnosis-pokt.nodies.app --port 8546 --no-deploy --config gnosisforked.config.ts", | ||
| "hh-local-deploy": "npx hardhat deploy --network localhost && cp -r deployments/localhost/*.json deployments/hardhat && cd ../web && yarn wagmi generate", | ||
| "verify:gnosis": "npx hardhat --network gnosis etherscan-verify --api-url https://api.gnosisscan.io", | ||
| "verify:gnosis": "npx hardhat --network gnosis etherscan-verify --api-url https://api.etherscan.io/v2/api?chainid=100", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
Confirm Etherscan v2 supports Gnosis (chainid=100) and task name.
The new endpoint looks right, but please verify:
- Etherscan v2 API handles chainid=100 (Gnosis).
- The Hardhat task
etherscan-verifyis correct for your plugin versions, and your ETHERSCAN_API_KEY works cross-chain.
🌐 Web query:
Does the Etherscan v2 API support Gnosis Chain (chainid=100) for contract verification, and is `etherscan-verify` the correct Hardhat task for @nomicfoundation/hardhat-verify v2?
💡 Result:
Short answer:
- Yes — Etherscan V2 supports Gnosis (chainId = 100) for contract verification. [1]
- For @nomicfoundation/hardhat-verify you should use the plugin's verify task (CLI: npx hardhat verify / programmatic subtask "verify:verify"); there is no documented "etherscan-verify" task. [2]
Sources:
- Etherscan V2 supported chains (lists Gnosis = 100). [Etherscan docs]. [1]
- @nomicfoundation/hardhat-verify docs — the plugin exposes the verify task and the "verify:verify" subtask (usage with Etherscan V2). [2]
Replace etherscan-verify with the correct Hardhat task
Etherscan V2 supports Gnosis (chainId 100), but @nomicfoundation/hardhat-verify v2 exposes verify (subtask verify:verify), not etherscan-verify. Update in contracts/package.json:
– "verify:gnosis": "npx hardhat --network gnosis etherscan-verify --api-url https://api.etherscan.io/v2/api?chainid=100",
+ "verify:gnosis": "npx hardhat --network gnosis verify --api-url https://api.etherscan.io/v2/api?chainId=100",Ensure your ETHERSCAN_API_KEY is set for cross-chain verification.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "verify:gnosis": "npx hardhat --network gnosis etherscan-verify --api-url https://api.etherscan.io/v2/api?chainid=100", | |
| "verify:gnosis": "npx hardhat --network gnosis verify --api-url https://api.etherscan.io/v2/api?chainId=100", |
🤖 Prompt for AI Agents
In contracts/package.json around line 8, the npm script uses the non-existent
hardhat task "etherscan-verify"; replace it with the correct Hardhat Verify task
"verify" (which invokes subtask verify:verify) and point to the same network and
api-url parameters so the script calls npx hardhat --network gnosis verify
--api-url https://api.etherscan.io/v2/api?chainid=100; also make sure the
ETHERSCAN_API_KEY environment variable is configured for cross-chain
verification.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
web/src/hooks/trade/index.ts (1)
303-332: Wrap 7702 executions with SeerCredits logic
tradeTokens7702currently ignoresprops.isSeerCreditswhen building its batched calls—bothgetUniswapTradeExecutionandgetSwaprTradeExecutionreturn raw executions. You must wrap each call withgetWrappedSeerCreditsExecution(props.isSeerCredits, props.trade, …)(as in the legacy flow) so that SeerCredits trades are correctly handled in the 7702 batch.
🧹 Nitpick comments (2)
web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx (2)
172-172: Verify consistency: isSeerCredits computed multiple times.The isSeerCredits helper is called inline at lines 172 and 302 rather than computing once and reusing. This is acceptable but slightly less efficient than storing the result.
Consider computing once at the component level:
const primaryCollateral = COLLATERAL_TOKENS[market.chainId].primary; const setPreferredCollateral = useGlobalState((state) => state.setPreferredCollateral); + const isSeerCreditsCollateral = isSeerCredits(market.chainId, selectedCollateral.address);Then reuse the variable in both locations (lines 172, 302).
575-575: Clean up commented code.The Futarchy-related code is commented out. If this feature is permanently removed, delete the comment. If it's temporarily disabled, add a TODO or explanation.
- {/* market.type === "Futarchy" && <FutarchyTokenSwitch market={market} outcomeIndex={outcomeIndex} /> */}
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
contracts/scripts/trading-credits.js(1 hunks)contracts/src/trading-credits/SeerCredits.sol(1 hunks)web/src/components/Market/SwapTokens/SwapTokens.tsx(1 hunks)web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx(5 hunks)web/src/components/Market/SwapTokens/SwapTokensMarket.tsx(3 hunks)web/src/components/Market/SwapTokens/TokenSelector.tsx(1 hunks)web/src/hooks/trade/index.ts(6 hunks)web/src/hooks/trade/useTradeConditions.ts(1 hunks)web/src/hooks/trade/utils.ts(2 hunks)web/src/hooks/useGlobalState.ts(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- contracts/scripts/trading-credits.js
- contracts/src/trading-credits/SeerCredits.sol
- web/src/components/Market/SwapTokens/SwapTokensMarket.tsx
🧰 Additional context used
🧬 Code graph analysis (5)
web/src/hooks/useGlobalState.ts (2)
web/src/lib/tokens.ts (1)
Token(8-13)web/src/lib/config.ts (1)
isSeerCredits(186-191)
web/src/hooks/trade/utils.ts (2)
web/src/hooks/useCheck7702Support.ts (1)
Execution(5-9)web/src/hooks/trade/index.ts (1)
getMaximumAmountIn(207-226)
web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx (2)
web/src/lib/config.ts (1)
isSeerCredits(186-191)web/src/lib/paths.ts (1)
paths(17-76)
web/src/hooks/trade/index.ts (5)
web/src/lib/chains.ts (3)
SupportedChain(30-30)mainnet(8-8)optimism(8-8)web/src/lib/tokens.ts (1)
Token(8-13)web/src/lib/config.ts (2)
isSeerCredits(186-191)COLLATERAL_TOKENS(39-73)web/src/hooks/trade/executeUniswapTrade.ts (1)
executeUniswapTrade(9-30)web/src/hooks/trade/executeSwaprTrade.ts (1)
executeSwaprTrade(12-35)
web/src/components/Market/SwapTokens/SwapTokens.tsx (1)
web/src/components/Dropdown.tsx (1)
Dropdown(14-50)
🔇 Additional comments (10)
web/src/components/Market/SwapTokens/TokenSelector.tsx (1)
45-45: LGTM!The
typeprop is correctly passed toCollateralDropdown, enabling it to conditionally include Seer Credits based on the transaction direction.web/src/hooks/useGlobalState.ts (1)
75-87: LGTM!The updated
getPreferredCollateralcorrectly filters Seer Credits only whenswapType === "sell", allowing regular ERC-20 tokens to remain as preferred collateral for all other cases. The logic aligns with the requirement that Seer Credits can only be used as a sell token in market orders.web/src/components/Market/SwapTokens/SwapTokens.tsx (1)
63-76: LGTM!The conditional rendering correctly hides the order-type dropdown for non-Generic markets (e.g., Futarchy), while preserving the default
orderType="market"behavior. This aligns with the requirement that Futarchy markets only support Market orders.web/src/hooks/trade/useTradeConditions.ts (1)
28-29: LGTM!The call to
getPreferredCollateralcorrectly passes bothmarket.chainIdandswapType, aligning with the updated API that conditionally filters Seer Credits based on transaction direction.web/src/hooks/trade/utils.ts (1)
157-182: Verify safety of Seer Credits execution
- Ensure
trade.outputAmount.currency.address!can never be undefined (native‐token trades would break at runtime) or add a guard to throw or fallback.- Confirm
creditsManagerAddress[trade.chainId]covers every chain where Seer Credits might be enabled—otherwise validate the chainId or handle missing mappings.web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx (2)
289-304: Past review issue addressed.The confirmation modal now receives the computed
isSeerCreditsflag at line 302, resolving the previous concern about hardcodingfalse.
377-386: Verify UI consistency: fixed primary collateral display.The limit price token display is now hardcoded to show
primaryCollateralinstead of dynamically switching based on secondary collateral state. This means users will always see the primary collateral symbol (e.g., sDAI) regardless of which collateral they're trading with.Ensure this change aligns with the intended UX:
- If users trade with Seer Credits, should they see primary collateral (sDAI/sUSDS) in the limit price display?
- Does this change affect how users understand the limit price they're setting?
The previous dynamic
renderLimitTokenDisplaylogic might have shown different tokens based onisSecondaryCollateral. Verify that removing this flexibility is intentional and doesn't confuse users trading with secondary or Seer Credits collateral.web/src/hooks/trade/index.ts (3)
154-160: LGTM: Correct isSeerCredits detection and collateral substitution.The logic correctly detects when the collateral is SeerCredits and substitutes it with the primary collateral token for quoting. The
shouldUseInstantSwapflag appropriately includes SeerCredits to bypass CoW quotes.
161-204: Verify quote routing: realCollateralToken used consistently.All three quote hooks (CoW, Swapr, Uniswap) now receive
realCollateralTokeninstead of the originalcollateralToken. This ensures quotes are computed against the actual underlying collateral (primary token) when SeerCredits are used.
262-278: LGTM: isSeerCredits propagated to trade execution.The
tradeTokensfunction correctly passesisSeerCreditsto bothexecuteUniswapTradeandexecuteSwaprTrade, enabling the CreditsManager wrapper logic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
web/src/lib/trade.ts (3)
133-138: Use exact fraction math for slippage; avoidNumber(...) / 100rounding.Current float conversion can drift for small decimals (e.g., 0.05%). Compute percent as a rational: x/(y*100).
-const slippage = String(Number(maxSlippage) / 100); -const [numerator, denominator] = parseFraction(slippage) ?? []; +const [num, den] = parseFraction(String(maxSlippage)) ?? []; +// percent => fraction-of-1: (num/den)/100 = num/(den*100) +const numerator = Number.isInteger(num) && Number.isInteger(den) ? num : 1; +const denominator = Number.isInteger(num) && Number.isInteger(den) ? den * 100 : 100; const maximumSlippage = - Number.isInteger(numerator) && Number.isInteger(denominator) - ? new Percent(String(numerator), String(denominator)) - : new Percent("1", "100"); + new Percent(String(numerator), String(denominator));
210-213: Wrong decimals for EXACT_INPUT quotes.
valueis the output amount; decimals should matchbuyToken, notsellToken.- decimals: args.sellToken.decimals, + decimals: args.buyToken.decimals,
29-38: IncludemaxSlippageingetSwaprQuote/getUniswapQuotecalls
Inweb/src/lib/market-odds.tsat lines 76–78 and 93–95, calls togetSwaprQuoteandgetUniswapQuoteomit the newmaxSlippageparameter. Add the appropriate slippage argument.web/src/lib/tradeExactOut.ts (2)
132-138: Exact fraction slippage (no floats).Mirror fix from
trade.tsto avoid rounding errors.-const slippage = String(Number(maxSlippage) / 100); -const [numerator, denominator] = parseFraction(slippage) ?? []; -const maximumSlippage = - Number.isInteger(numerator) && Number.isInteger(denominator) - ? new Percent(String(numerator), String(denominator)) - : new Percent("1", "100"); +const [num, den] = parseFraction(String(maxSlippage)) ?? []; +const numerator = Number.isInteger(num) && Number.isInteger(den) ? num : 1; +const denominator = Number.isInteger(num) && Number.isInteger(den) ? den * 100 : 100; +const maximumSlippage = new Percent(String(numerator), String(denominator));
158-169: Fix missingisFastQueryarg inget*QuoteExactOutcall-sites
Pass the newisFastQueryparameter to allget*QuoteExactOutcalls inweb/src/hooks/trade/index.tsat lines 55, 112, and 157.web/src/hooks/trade/index.ts (1)
320-349: In tradeTokens7702 (web/src/hooks/trade/index.ts:320-349), wrap the Uniswap and Swapr executions withgetWrappedSeerCreditsExecutionwhenprops.isSeerCreditsis true to preserve Seer Credits support.
🧹 Nitpick comments (4)
web/src/lib/market-odds.ts (2)
116-124: Avoid importing state from hooks in lib; passmaxSlippageas a param instead.Pulling
useGlobalStateinto a lib module risks circular deps and SSR quirks. ThreadmaxSlippagefrom callers (e.g.,getTokenPrice→getTokenPriceFromSwap→getTokenSwapResult) to keep lib pure/testable.
125-136: Handle zero-quote explicitly to avoidInfinitymath.When quote is
0n,BUY_AMOUNT / Number(formatUnits(0n))yieldsInfinity. Short-circuit before division for clearer intent.-const pricePerShare = BUY_AMOUNT / Number(formatUnits(price, 18)); +if (price === 0n) return Number.NaN; +const pricePerShare = BUY_AMOUNT / Number(formatUnits(price, 18));web/src/lib/trade.ts (1)
118-149: Deduplicate slippage computation across files.
getTradeArgshere and intradeExactOut.tsduplicate the slippage parse logic; extract a shared helper (e.g.,computeMaximumSlippage(maxSlippage: string): Percent) to avoid drift.web/src/lib/tradeExactOut.ts (1)
19-39: Centralize shared quote types.
QuoteTradeResultandQuoteTradeFnare defined here and intrade.ts. Extract tolib/tradeTypes.tsand import in both to prevent future drift.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
web/src/hooks/trade/index.ts(10 hunks)web/src/lib/market-odds.ts(5 hunks)web/src/lib/trade.ts(6 hunks)web/src/lib/tradeExactOut.ts(6 hunks)
🧰 Additional context used
🧬 Code graph analysis (4)
web/src/lib/trade.ts (1)
web/src/lib/tradeExactOut.ts (1)
getTradeArgs(117-148)
web/src/lib/market-odds.ts (1)
web/src/lib/trade.ts (2)
getSwaprQuote(221-253)getUniswapQuote(187-219)
web/src/hooks/trade/index.ts (5)
web/src/lib/trade.ts (3)
getSwaprQuote(221-253)getCowQuote(151-185)getUniswapQuote(187-219)web/src/lib/tradeExactOut.ts (3)
getSwaprQuoteExactOut(227-260)getCowQuoteExactOut(158-191)getUniswapQuoteExactOut(193-225)web/src/lib/config.ts (2)
isSeerCredits(186-191)COLLATERAL_TOKENS(39-73)web/src/hooks/trade/executeUniswapTrade.ts (1)
executeUniswapTrade(9-30)web/src/hooks/trade/executeSwaprTrade.ts (1)
executeSwaprTrade(12-35)
web/src/lib/tradeExactOut.ts (1)
web/src/lib/trade.ts (1)
getTradeArgs(118-149)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Redirect rules - seer-pm
- GitHub Check: Header rules - seer-pm
- GitHub Check: Pages changed - seer-pm
🔇 Additional comments (9)
web/src/hooks/trade/index.ts (9)
5-5: LGTM: Imports added for Seer Credits support.The new imports
COLLATERAL_TOKENSandisSeerCreditsare correctly specified and used later in the file to handle Seer Credits collateral logic.
33-35: Previous concern resolved: maxSlippage now properly propagated.The
maxSlippageparameter is now correctly passed through togetSwaprQuoteandgetSwaprQuoteExactOut(lines 54-55), addressing the previous review comment about unused parameters in query keys.Also applies to: 54-55
89-91: Previous concern resolved: maxSlippage now properly propagated.The
maxSlippageparameter is now correctly passed through togetCowQuoteandgetCowQuoteExactOut(lines 111-121), addressing the previous review comment.Also applies to: 111-121
134-136: Previous concern resolved: maxSlippage now properly propagated.The
maxSlippageparameter is now correctly passed through togetUniswapQuoteandgetUniswapQuoteExactOut(lines 156-157), addressing the previous review comment.Also applies to: 156-157
171-177: LGTM: Seer Credits collateral handling is well-structured.The logic correctly:
- Detects Seer Credits collateral via
isSeerCredits- Maps it to the underlying primary collateral token for quote computations
- Forces instant swap mode when Seer Credits are used
This ensures quotes are fetched for the real underlying token while maintaining the Seer Credits execution path.
224-243: LGTM: Export enables external usage.Exporting
getMaximumAmountInis correct; it's imported and used inweb/src/hooks/trade/utils.tsfor the Seer Credits execution wrapper.
271-277: LGTM: Interface extended to support Seer Credits.The
isSeerCreditsproperty addition toTradeTokensPropscorrectly extends the interface to propagate the Seer Credits execution flag through trade functions.
279-295: LGTM: isSeerCredits propagated correctly to execution functions.The
isSeerCreditsflag is properly:
- Destructured from props
- Passed to
executeUniswapTradeandexecuteSwaprTrade- Not used in CoW path (expected, as Seer Credits only work with instant swaps)
218-221: Incorrect chain reference The review comment refers tobase.id, but the code’s fallback logic checksmainnet.id(andoptimism.id), so the premise is invalid.Likely an incorrect or invalid review comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
contracts/deployments/gnosis/CreditsManager.json (1)
270-340: Clear router allowance after swaps.
executesetstoken.approve(to, amount)and never resets it. Any whitelisted router (or one subsequently compromised) can keep that allowance and drain the manager’s collateral later without burning credits. Please zero the allowance after the swap (and ideally before re-approving) so no residual spend permission remains.- require(token.approve(to, amount), "Token approval failed"); + require(token.approve(to, 0), "Token approval reset failed"); + require(token.approve(to, amount), "Token approval failed"); ... - require(balanceAfter > balanceBefore, "No tokens received from swap"); + require(balanceAfter > balanceBefore, "No tokens received from swap"); + require(token.approve(to, 0), "Token approval clear failed");web/src/hooks/trade/index.ts (1)
330-359: Missing Seer Credits execution wrapping in 7702 path.The
tradeTokens7702function doesn't wrap trade executions for Seer Credits. In the legacy path,executeUniswapTradeandexecuteSwaprTradecallgetWrappedSeerCreditsExecutionto route trades through CreditsManager whenisSeerCreditsis true (see web/src/hooks/trade/executeUniswapTrade.ts:13-16).The 7702 path (lines 337-341) directly calls
getUniswapTradeExecution/getSwaprTradeExecutionwithout wrapping, so Seer Credits trades via 7702 will bypass CreditsManager and likely fail.Apply this pattern to wrap executions before adding to calls:
import { getWrappedSeerCreditsExecution } from "@/hooks/trade/utils"; // In tradeTokens7702, replace lines 337-341: const execution = props.trade instanceof UniswapTrade ? await getUniswapTradeExecution(props.trade, props.account) : await getSwaprTradeExecution(props.trade, props.account, props.isBuyExactOutputNative, props.isSellToNative); const wrappedExecution = getWrappedSeerCreditsExecution( props.isSeerCredits, props.trade, execution, ); calls.push(wrappedExecution);If
getWrappedSeerCreditsExecutionneeds to be refactored to work with 7702Executiontype, ensure it returns the correct type forsendCalls.
♻️ Duplicate comments (1)
contracts/deployments/gnosis/SeerCredits.json (1)
180-212: Prevent bricking creditsManager.
changeCreditsManagerstill allows setting the manager to the zero address. Doing so irreversibly blocksburncalls and breaks credit spends. Please add a non-zero guard (and optionally emit an event) before permitting the update.function changeCreditsManager(address _creditsManager) external onlyGovernor { - creditsManager = _creditsManager; + require(_creditsManager != address(0), "Invalid credits manager"); + creditsManager = _creditsManager; }
🧹 Nitpick comments (1)
web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx (1)
578-578: Remove commented-out code.The Futarchy-related code is commented out. If this code is no longer needed (as suggested by the PR summary), remove it entirely rather than leaving it as a comment.
Apply this diff:
- {/* market.type === "Futarchy" && <FutarchyTokenSwitch market={market} outcomeIndex={outcomeIndex} /> */} <div className="w-full text-[12px] text-black-secondary flex items-center gap-2">
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
contracts/deployments/gnosis/CreditsManager.json(1 hunks)contracts/deployments/gnosis/SeerCredits.json(1 hunks)web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx(7 hunks)web/src/components/Market/SwapTokens/SwapTokensMarket.tsx(5 hunks)web/src/hooks/trade/index.ts(12 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- web/src/components/Market/SwapTokens/SwapTokensMarket.tsx
🧰 Additional context used
🧬 Code graph analysis (2)
web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx (3)
web/src/lib/config.ts (1)
isSeerCredits(186-191)web/src/hooks/trade/index.ts (1)
useTrade(382-393)web/src/lib/paths.ts (1)
paths(17-76)
web/src/hooks/trade/index.ts (5)
web/src/lib/trade.ts (2)
getCowQuote(151-185)getUniswapQuote(187-219)web/src/lib/chains.ts (3)
SupportedChain(30-30)mainnet(8-8)optimism(8-8)web/src/lib/config.ts (2)
isSeerCredits(186-191)COLLATERAL_TOKENS(39-73)web/src/hooks/trade/executeUniswapTrade.ts (1)
executeUniswapTrade(9-30)web/src/hooks/trade/executeSwaprTrade.ts (1)
executeSwaprTrade(12-35)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Redirect rules - seer-pm
- GitHub Check: Header rules - seer-pm
- GitHub Check: Pages changed - seer-pm
🔇 Additional comments (7)
web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx (3)
10-10: LGTM!The import of
isSeerCreditsand the computation ofisSeerCreditsCollateralare correct and align with the PR's objective to integrate Seer Credits into the trade flow.Also applies to: 12-12, 143-143
164-164: LGTM!The
isSeerCreditsflag is correctly propagated throughuseTrade,tradeTokens.mutateAsync, andSwapTokensConfirmation. This addresses the previous review feedback about hardcoded values.Also applies to: 175-175, 305-305
380-389: Verify collateral‐symbol consistency in SwapTokensLimitUpToLimit-price input always shows
primaryCollateral.symbol, but the Avg price display usesselectedCollateral.symbolwhen trading with secondary collateral (e.g. Seer Credits). This mismatch may confuse users. Please confirm whether to:
- Also show
primaryCollateral.symbolin the Avg price display for secondary trades,- Revert the limit-price input to use
selectedCollateral.symbolwhenisSecondaryCollateral, or- Add a note clarifying that limit orders are always quoted in primary collateral.
web/src/hooks/trade/index.ts (4)
5-5: LGTM!The addition of
COLLATERAL_TOKENSandisSeerCreditsimports, along with theEMPTY_APPROVALSconstant, correctly support the Seer Credits integration. The constant is appropriately used to bypass traditional approval flows when Seer Credits or 7702 delegation is active.Also applies to: 26-29
31-63: LGTM!The quote hook signatures (
useSwaprQuote,useCowQuote,useUniswapQuote) have been consistently updated to acceptenabled,tradeType, andmaxSlippageparameters. ThemaxSlippageparameter is now properly propagated to the underlying quote functions, addressing the previous review feedback.Also applies to: 87-130, 132-165
167-227: LGTM!The
useQuoteTraderefactor correctly implements Seer Credits support:
- Converts Seer Credits to the primary collateral for quoting (line 178)
- Automatically enables instant swap mode for Seer Credits (line 182)
- Disables CoW quotes when instant swap is needed (line 190)
- Prioritizes Uniswap on mainnet/optimism (line 223)
The logic aligns with the architectural decision to route Seer Credits trades through CreditsManager while using primary collateral for pricing.
276-282: LGTM!The
isSeerCreditsflag is correctly propagated through the legacy trade execution path:
- Added to
TradeTokensPropsinterface (line 281)- Passed through
tradeTokensto execution functions (lines 296, 299)- Used in
useTradeLegacyto returnEMPTY_APPROVALSwhen active (line 313)- Exposed via
useTradepublic API (line 385)The logic correctly bypasses traditional approvals for Seer Credits trades, as CreditsManager handles authorization internally.
Also applies to: 284-300, 302-328, 382-393
Summary by CodeRabbit
New Features
Enhancements
Chores