Skip to content

Conversation

@xyzseer
Copy link
Collaborator

@xyzseer xyzseer commented Sep 27, 2025

Summary by CodeRabbit

  • New Features

    • Adds Seer Credits token and Credits Manager to enable swaps payable with credits, DEX whitelisting, batch credit management, and admin roles.
    • UI displays SEER_CREDITS in confirmations, a custom Seer Credits icon, and collateral selector adapts to buy vs. sell.
  • Enhancements

    • Trade flow wraps executions via Credits Manager when using Seer Credits; slippage is now explicitly passed through quote and execution flows.
    • Order-type selector hidden for markets that only support market orders.
  • Chores

    • Deployment artifacts, scripts, contract mapping and verification script updated for Gnosis.

@netlify
Copy link

netlify bot commented Sep 27, 2025

Deploy Preview for seer-pm ready!

Name Link
🔨 Latest commit a867a62
🔍 Latest deploy log https://app.netlify.com/projects/seer-pm/deploys/68e451d531fc900008fcbcfc
😎 Deploy Preview https://deploy-preview-399--seer-pm.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link

coderabbitai bot commented Sep 27, 2025

Walkthrough

Adds 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

Cohort / File(s) Summary
Contracts: Trading Credits (Solidity)
contracts/src/trading-credits/SeerCredits.sol, contracts/src/trading-credits/CreditsManager.sol
New SeerCredits ERC20 with governor/admin/creditsManager roles, batch/admin minting, and burn; new CreditsManager that validates credits, burns user credits, proxies swaps to whitelisted DEX routers, and verifies recipient receipt.
Deployments & Deploy Script
contracts/deploy/30-deploy-credits-manager.ts, contracts/deployments/gnosis/SeerCredits.json, contracts/deployments/gnosis/CreditsManager.json
New deploy script deploying SeerCredits and CreditsManager, wiring changeCreditsManager; adds Gnosis deployment artifacts with ABI/bytecode/metadata/storage layout.
Ops Script
contracts/scripts/trading-credits.js
New script to batch-set SeerCredits balances and whitelist contracts via deployed SeerCredits and CreditsManager.
Contracts package
contracts/package.json
Updated verify:gnosis script to use etherscan API with chainId=100.
Frontend: Trade hooks & execution utils
web/src/hooks/trade/index.ts, web/src/hooks/trade/utils.ts, web/src/hooks/trade/executeUniswapTrade.ts, web/src/hooks/trade/executeSwaprTrade.ts, web/src/hooks/trade/*
Propagates isSeerCredits and explicit maxSlippage through quote and trade APIs; adds getWrappedSeerCreditsExecution to wrap executions with CreditsManager.execute; Uniswap/Swapr execution functions accept isSeerCredits and send wrapped execution when true.
Frontend: Trade orchestration & state
web/src/hooks/trade/useTradeConditions.ts, web/src/hooks/useGlobalState.ts, web/src/hooks/useGlobalState.ts
getPreferredCollateral signature updated to (chainId, swapType); logic updated to restrict SEER_CREDITS to sell-market flows and adjust selectedCollateral accordingly.
Frontend: Components (Market / Swap)
web/src/components/Market/CollateralDropdown.tsx, web/src/components/Market/TokenSelector.tsx, web/src/components/Market/SwapTokens/SwapTokensMarket.tsx, .../SwapTokens/SwapTokensLimitUpTo.tsx, .../SwapTokens/SwapTokensConfirmation.tsx, web/src/components/Market/SwapTokens/SwapTokens.tsx
Threaded new props: `type: "buy"
Frontend: Helpers & assets
web/src/lib/config.ts, web/src/lib/paths.ts
Added isSeerCredits(chainId, tokenAddress) helper and special-cased tokenImage for SeerCredits.
Frontend: Wagmi mapping
web/wagmi.config.ts
Added "trading-credits" mapping for SeerCredits and CreditsManager.
Frontend: Slippage & quote surfaces
web/src/lib/trade.ts, web/src/lib/tradeExactOut.ts, web/src/lib/market-odds.ts
Introduced explicit maxSlippage parameter propagated through quote/trade call chains; updated quote function signatures and call sites to accept and forward maxSlippage.

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
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • batch trades #395 — Overlaps refactoring of execution abstraction and 7702/batching helpers used by the SeerCredits wrapping in executeSwaprTrade/executeUniswapTrade.
  • improve swap ux #369 — Modifies trade execution flows and utilities; closely related to the new wrapping behavior and signature changes.
  • batch approve #318 — Introduced the Execution abstraction and 7702 batching/sendCalls support that getWrappedSeerCreditsExecution relies on.

Poem

A rabbit in a dev hat, quick and bright,
I wrap swaps in a manager by moonlight.
Burn credits, hop through routers with glee,
Whitelist the paths, then set traders free.
Thump-thump — trades complete, carrots for me! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title “trading credits” is a generic noun phrase that lacks a clear action or context and does not succinctly convey the primary change introduced by this pull request. It does reference the feature area but fails to form a descriptive summary that would help a reviewer or teammate understand what was added or modified. Please revise the title to a concise, imperative phrase that highlights the main change, such as “Add trading credits support with SeerCredits and CreditsManager” or “Introduce SeerCredits token and CreditsManager for trading credits functionality.”
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/trading-credits

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.

❤️ Share

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

Copy link

@coderabbitai coderabbitai bot left a 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 suggested

Implementation 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.enabled is 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

📥 Commits

Reviewing files that changed from the base of the PR and between 239c8c7 and 8215c6e.

📒 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: Propagating type to 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 pass creditsManagerAddress[trade.chainId] as the spender when isSeerCredits is true.
web/src/components/Market/CollateralDropdown.tsx (1)

18-19: All CollateralDropdown usages include the new type prop. No additional call sites found; no further changes required.

web/src/lib/paths.ts (1)

70-72: Asset path validated: file exists at web/public/assets/android-icon-192x192.png and no Next.js basePath is configured, so returning /assets/android-icon-192x192.png will resolve correctly.

web/src/components/Market/SwapTokens/SwapTokensLimitUpTo.tsx (1)

10-10: LGTM: wiring isSeerCredits import and orderType="limit" into trade conditions

Both 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 handling

Good 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 address 0x3a0D8671eFcBc172eDBE32F91169BBc984dC607C. Re-run your codegen or manually update seerCreditsAddress[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",
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

🧩 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-verify is 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:

  1. Etherscan V2 supported chains (lists Gnosis = 100). [Etherscan docs]. [1]
  2. @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.

Suggested change
"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.

Copy link

@coderabbitai coderabbitai bot left a 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
tradeTokens7702 currently ignores props.isSeerCredits when building its batched calls—both getUniswapTradeExecution and getSwaprTradeExecution return raw executions. You must wrap each call with getWrappedSeerCreditsExecution(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

📥 Commits

Reviewing files that changed from the base of the PR and between 8215c6e and b421548.

📒 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 type prop is correctly passed to CollateralDropdown, enabling it to conditionally include Seer Credits based on the transaction direction.

web/src/hooks/useGlobalState.ts (1)

75-87: LGTM!

The updated getPreferredCollateral correctly filters Seer Credits only when swapType === "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 getPreferredCollateral correctly passes both market.chainId and swapType, 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 isSeerCredits flag at line 302, resolving the previous concern about hardcoding false.


377-386: Verify UI consistency: fixed primary collateral display.

The limit price token display is now hardcoded to show primaryCollateral instead 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 renderLimitTokenDisplay logic might have shown different tokens based on isSecondaryCollateral. 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 shouldUseInstantSwap flag appropriately includes SeerCredits to bypass CoW quotes.


161-204: Verify quote routing: realCollateralToken used consistently.

All three quote hooks (CoW, Swapr, Uniswap) now receive realCollateralToken instead of the original collateralToken. 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 tradeTokens function correctly passes isSeerCredits to both executeUniswapTrade and executeSwaprTrade, enabling the CreditsManager wrapper logic.

Copy link

@coderabbitai coderabbitai bot left a 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; avoid Number(...) / 100 rounding.

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.

value is the output amount; decimals should match buyToken, not sellToken.

-    decimals: args.sellToken.decimals,
+    decimals: args.buyToken.decimals,

29-38: Include maxSlippage in getSwaprQuote/getUniswapQuote calls
In web/src/lib/market-odds.ts at lines 76–78 and 93–95, calls to getSwaprQuote and getUniswapQuote omit the new maxSlippage parameter. Add the appropriate slippage argument.

web/src/lib/tradeExactOut.ts (2)

132-138: Exact fraction slippage (no floats).

Mirror fix from trade.ts to 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 missing isFastQuery arg in get*QuoteExactOut call-sites
Pass the new isFastQuery parameter to all get*QuoteExactOut calls in web/src/hooks/trade/index.ts at 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 with getWrappedSeerCreditsExecution when props.isSeerCredits is 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; pass maxSlippage as a param instead.

Pulling useGlobalState into a lib module risks circular deps and SSR quirks. Thread maxSlippage from callers (e.g., getTokenPricegetTokenPriceFromSwapgetTokenSwapResult) to keep lib pure/testable.


125-136: Handle zero-quote explicitly to avoid Infinity math.

When quote is 0n, BUY_AMOUNT / Number(formatUnits(0n)) yields Infinity. 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.

getTradeArgs here and in tradeExactOut.ts duplicate 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.

QuoteTradeResult and QuoteTradeFn are defined here and in trade.ts. Extract to lib/tradeTypes.ts and import in both to prevent future drift.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b421548 and 7c8d044.

📒 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_TOKENS and isSeerCredits are correctly specified and used later in the file to handle Seer Credits collateral logic.


33-35: Previous concern resolved: maxSlippage now properly propagated.

The maxSlippage parameter is now correctly passed through to getSwaprQuote and getSwaprQuoteExactOut (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 maxSlippage parameter is now correctly passed through to getCowQuote and getCowQuoteExactOut (lines 111-121), addressing the previous review comment.

Also applies to: 111-121


134-136: Previous concern resolved: maxSlippage now properly propagated.

The maxSlippage parameter is now correctly passed through to getUniswapQuote and getUniswapQuoteExactOut (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 getMaximumAmountIn is correct; it's imported and used in web/src/hooks/trade/utils.ts for the Seer Credits execution wrapper.


271-277: LGTM: Interface extended to support Seer Credits.

The isSeerCredits property addition to TradeTokensProps correctly extends the interface to propagate the Seer Credits execution flag through trade functions.


279-295: LGTM: isSeerCredits propagated correctly to execution functions.

The isSeerCredits flag is properly:

  • Destructured from props
  • Passed to executeUniswapTrade and executeSwaprTrade
  • Not used in CoW path (expected, as Seer Credits only work with instant swaps)

218-221: Incorrect chain reference The review comment refers to base.id, but the code’s fallback logic checks mainnet.id (and optimism.id), so the premise is invalid.

Likely an incorrect or invalid review comment.

Copy link

@coderabbitai coderabbitai bot left a 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.

execute sets token.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 tradeTokens7702 function doesn't wrap trade executions for Seer Credits. In the legacy path, executeUniswapTrade and executeSwaprTrade call getWrappedSeerCreditsExecution to route trades through CreditsManager when isSeerCredits is true (see web/src/hooks/trade/executeUniswapTrade.ts:13-16).

The 7702 path (lines 337-341) directly calls getUniswapTradeExecution / getSwaprTradeExecution without 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 getWrappedSeerCreditsExecution needs to be refactored to work with 7702 Execution type, ensure it returns the correct type for sendCalls.

♻️ Duplicate comments (1)
contracts/deployments/gnosis/SeerCredits.json (1)

180-212: Prevent bricking creditsManager.

changeCreditsManager still allows setting the manager to the zero address. Doing so irreversibly blocks burn calls 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

📥 Commits

Reviewing files that changed from the base of the PR and between 7c8d044 and a867a62.

📒 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 isSeerCredits and the computation of isSeerCreditsCollateral are 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 isSeerCredits flag is correctly propagated through useTrade, tradeTokens.mutateAsync, and SwapTokensConfirmation. This addresses the previous review feedback about hardcoded values.

Also applies to: 175-175, 305-305


380-389: Verify collateral‐symbol consistency in SwapTokensLimitUpTo

Limit-price input always shows primaryCollateral.symbol, but the Avg price display uses selectedCollateral.symbol when trading with secondary collateral (e.g. Seer Credits). This mismatch may confuse users. Please confirm whether to:

  • Also show primaryCollateral.symbol in the Avg price display for secondary trades,
  • Revert the limit-price input to use selectedCollateral.symbol when isSecondaryCollateral, 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_TOKENS and isSeerCredits imports, along with the EMPTY_APPROVALS constant, 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 accept enabled, tradeType, and maxSlippage parameters. The maxSlippage parameter 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 useQuoteTrade refactor correctly implements Seer Credits support:

  1. Converts Seer Credits to the primary collateral for quoting (line 178)
  2. Automatically enables instant swap mode for Seer Credits (line 182)
  3. Disables CoW quotes when instant swap is needed (line 190)
  4. 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 isSeerCredits flag is correctly propagated through the legacy trade execution path:

  1. Added to TradeTokensProps interface (line 281)
  2. Passed through tradeTokens to execution functions (lines 296, 299)
  3. Used in useTradeLegacy to return EMPTY_APPROVALS when active (line 313)
  4. Exposed via useTrade public 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

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.

2 participants