Skip to content

Conversation

@gonzaotc
Copy link
Contributor

@gonzaotc gonzaotc commented Aug 13, 2025

Pending:

v0.0.0.alpha

  • Make the Pausable option to pause common entry points and custom external/public non-view functions by default.
  • When enabling extra permissions, add the respective permission hook function to the output.
  • Make shares required in BaseCustomAccounting & BaseCustomCurve
  • Simplify Hook names
  • Simplify imports
  • Add tests covering compilation and snapshots on every option and multiple hook permissions config
  • Update Uniswap Hooks project with latest changes to point to master instead of specific commit
  • Include Oracles
  • Add input validations
  • Add a changeset for the solidity package

Next release in a posterior PR:

  • Fix full inheritance linearization by refactoring BaseHook and adding respective .super calls in inheriting hooks contracts.
  • Enable multiple hook selection.

@gonzaotc gonzaotc requested review from a team as code owners August 13, 2025 00:20
@gonzaotc gonzaotc marked this pull request as draft August 13, 2025 00:20
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Aug 13, 2025

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

Walkthrough

This pull request introduces comprehensive Uniswap v4 Hooks support to the OpenZeppelin Wizard. It adds a new uniswap-hooks package with hook generators, updates core solidity abstractions to support libraries and top-level comments, extends the UI with hooks configuration controls, integrates MCP tooling, and wires everything together across packages.

Changes

Cohort / File(s) Summary
New Uniswap Hooks Package
packages/core/uniswap-hooks/
New complete package for Uniswap v4 hooks integration including 15+ hook implementations (BaseHook, BaseAsyncSwap, BaseCustomAccounting, etc.), configuration options, generator, and test infrastructure
Hook Implementations
packages/core/uniswap-hooks/src/hooks/{BaseHook,AntiSandwichHook,BaseDynamicFee,LimitOrderHook,LiquidityPenaltyHook,...}.ts
Defines 15 hook types with metadata, permissions, function signatures, and shares configuration
Hooks API & Generation
packages/core/uniswap-hooks/src/{hooks,api,build-generic,generate/hooks,generate/sources}.ts
Core hooks generator with options validation, contract building, and permutation generation for comprehensive testing
Package Configuration
packages/core/uniswap-hooks/{package.json,ava.config.js,hardhat.config.js,tsconfig.json,remappings.txt}
Build, test, and Solidity compilation configuration for hooks package
Solidity Core Updates
packages/core/solidity/src/contract.ts
Extended Contract/ContractBuilder with topLevelComments, libraries (replacing Using), constructionOnly relationships, and FunctionKind expansion (added private/external)
Print & Compatibility
packages/core/solidity/src/{print.ts,options.ts,utils/imports-libraries.ts}
Enhanced printing to support libraries and top-level comments; updated compatibility banner; refactored library import checks to be generic
Index Exports
packages/core/solidity/src/index.ts
Expanded public API exports for new types (BaseFunction, Value, ReferencedContract) and utilities (generateAlternatives, accessOptions, etc.)
Snapshot Updates
packages/core/solidity/src/{contract.test.ts.md,custom.test.ts.md,zip-foundry.test.ts.md,zip-hardhat.test.ts.md}
Removed OpenZeppelin compatibility comment lines from generated contract snapshots
Common Descriptions
packages/common/src/{ai/descriptions/uniswap-hooks.ts,index.ts}
Added descriptive metadata exports for hooks prompts, permissions, shares, and inputs
UI Main Integration
packages/ui/src/main.ts
Added uniswap-hooks app type and compatibility evaluation logic
UI Components
packages/ui/src/uniswap-hooks/{App.svelte,HooksControls.svelte,SharesControlsSection.svelte}
New Svelte components for hooks configuration UI with expandable sections, dynamic inputs, and permission management
UI Utilities
packages/ui/src/uniswap-hooks/{inject-hyperlinks.ts,test.ts}
Hyperlink injection utility and test setup for hooks UI
UI Component Updates
packages/ui/src/common/{ExpandableSection.svelte,ParentExpandableSection.svelte}
New ExpandableSection component and type extension for section variant
UI Types & Configuration
packages/ui/src/common/{languages-types.ts,styles/vars.css}
packages/ui/tailwind.config.js
Added uniswap-hooks language type, pink color variable, and Tailwind spacing token
UI Navigation
packages/ui/public/{index.html,cairo.html,stellar.html,stylus.html,uniswap-hooks.html}
Added uniswap-hooks navigation links to all HTML pages and created full uniswap-hooks.html page
AI Assistant Integration
packages/ui/api/ai-assistant/function-definitions/{uniswap-hooks.ts,shared.ts}
packages/ui/api/ai-assistant/types/{assistant.ts,languages.ts}
Added hooks AI function definitions, exported shared function descriptions, and extended language/options types with DistributivePartial utility
MCP Tooling
packages/mcp/src/uniswap-hooks/{schemas.ts,tools.ts,tools/hooks.ts,tools/hooks.test.ts*}
Zod schemas, tool registration, and comprehensive test suite for hooks MCP integration
MCP Wiring
packages/mcp/{package.json,src/index.ts,src/server.ts}
Added uniswap-hooks dependency and registerUniswapHooksTools export; updated server setup
Documentation
packages/core/uniswap-hooks/{README.md,CHANGELOG.md,LICENSE,NOTICE}
.github/{CODEOWNERS,workflows/test.yml}
Added package documentation, license/notice files, code ownership assignments, and test CI matrix
Miscellaneous
packages/core/uniswap-hooks/{.gitignore,src/importPaths.json,src/index.ts,src/kind.ts,src/print.ts,src/test.ts,src/utils/version.ts}
Import path mappings, kind sanitization, version constant, test infrastructure, and module re-exports

Sequence Diagram(s)

sequenceDiagram
    participant User as User
    participant UI as UI (HooksControls)
    participant API as buildGeneric<br/>(hooks.ts)
    participant Builder as ContractBuilder
    participant Printer as printContract
    participant Output as Generated Code

    User->>UI: Configure hook options<br/>(hook type, permissions, shares)
    UI->>API: Call buildHooks(opts)
    API->>Builder: new ContractBuilder()
    API->>Builder: applyCommonDefaults()
    API->>Builder: addAccessControl()
    API->>Builder: addCurrencySettler()
    API->>Builder: addSafeCast()
    API->>Builder: addTransientStorage()
    API->>Builder: addShares (ERC20/6909/1155)
    API->>Builder: addHook(hook type)<br/>+ permissions setup
    Builder-->>API: Contract object
    UI->>Printer: printContract(contract, opts)
    Printer->>Printer: printTopLevelComments()
    Printer->>Printer: printLibraries()
    Printer->>Printer: printCompatibleLibraryVersions()
    Printer-->>UI: Solidity code
    UI->>Output: Display with<br/>syntax highlighting
    User->>Output: Copy/Download/Remix
Loading
sequenceDiagram
    participant Client as MCP Client
    participant Server as MCP Server
    participant Handler as registerUniswapHooks
    participant Generator as buildGeneric
    participant Printer as printSolidityContract
    participant Response as Tool Response

    Client->>Server: Call uniswapHooks tool<br/>with hook config params
    Server->>Handler: Tool input received
    Handler->>Generator: buildGeneric(opts)
    Generator-->>Handler: Contract object
    Handler->>Printer: printSolidityContract(contract, opts)
    Printer->>Printer: Add additionalCompatibleLibraries<br/>for OpenZeppelin Uniswap Hooks
    Printer-->>Handler: Solidity code string
    Handler->>Response: Wrap code in<br/>safePrintSolidityCodeBlock()
    Response-->>Client: Tool response with<br/>Solidity code block
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

This PR introduces substantial new functionality with high complexity: a complete new hooks package with 15+ hook implementations, significant extensions to core solidity abstractions (Contract/ContractBuilder public APIs, library support), dense logic for permission management and contract building, new UI components with reactive state management, and MCP tooling integration. The heterogeneity spans multiple packages with varying logic density. Multiple integration points require verification of correctness across the ecosystem (type safety, API consistency, import resolution).

Possibly related PRs

Suggested reviewers

  • ericglau
  • ernestognw
  • CoveMB

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.07% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title Check ✅ Passed The PR title "Hooks Wizard v0.0.1" is fully related to the main change in the changeset. The pull request introduces a comprehensive new Uniswap Hooks Wizard feature across multiple packages, including a new packages/core/uniswap-hooks/ package with extensive hook definitions and configurations, UI components for hook management in the wizard interface, MCP server integration for tools, and updates to support this new feature throughout the codebase. The title clearly identifies this primary change and includes a version number, making it specific and meaningful for someone scanning the repository history.
Description Check ✅ Passed The pull request description is directly related to the changeset. The author provides a specific checklist for v0.0.0.alpha that enumerates completed work items including Pausable option enhancements, permission hook functions, shares configuration requirements, hook simplification, import optimization, test coverage, Uniswap Hooks project updates, oracle support, input validation, and a changeset for the solidity package. Each of these items corresponds to specific changes present in the raw summary: new hook implementations (BaseHook, BaseAsyncSwap, BaseCustomAccounting, etc.), support for multiple share token types (ERC20, ERC1155, ERC6909), test files covering compilation and snapshots, oracle hook implementations, input validation logic in hooks.ts, and configuration updates. The description is concrete, version-labeled, and clearly communicates the scope and completion status of the implemented features without being vague or generic.

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.

@github-actions
Copy link
Contributor

github-actions bot commented Aug 13, 2025

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@qodo-merge-pro
Copy link

PR Type

Enhancement


Description

  • Add Uniswap Hooks wizard with comprehensive contract generation

  • Implement using directive support in Solidity contract builder

  • Create new UI interface for Uniswap Hooks configuration

  • Add navigation and routing for new wizard type


Diagram Walkthrough

flowchart LR
  A["Core Solidity"] --> B["Using Directives"]
  C["Uniswap Hooks Core"] --> D["Hook Types"]
  C --> E["Contract Builder"]
  F["UI Components"] --> G["Hooks Controls"]
  F --> H["Navigation"]
  I["Public Pages"] --> J["Routing"]
  D --> K["Generated Contract"]
  E --> K
Loading

File Walkthrough

Relevant files
Enhancement
20 files
contract.ts
Add using directive support to contract builder                   
+10/-0   
print.ts
Implement using directive printing functionality                 
+18/-0   
api.ts
Create main API interface for hooks wizard                             
+16/-0   
build-generic.ts
Implement generic contract builder for hooks                         
+16/-0   
hooks.ts
Add hooks options generation utilities                                     
+31/-0   
hooks.ts
Core hooks contract building and configuration logic         
+230/-0 
index.ts
Main export file for hooks package                                             
+12/-0   
kind.ts
Kind validation and sanitization utilities                             
+26/-0   
languages-types.ts
Add uniswap-hooks language type support                                   
+4/-2     
main.ts
Integrate uniswap-hooks app routing and initialization     
+13/-1   
inject-hyperlinks.ts
Add hyperlink injection for contract imports                         
+18/-0   
remix.ts
Implement Remix IDE integration utilities                               
+15/-0   
AccessControlSection.svelte
Create access control configuration component                       
+62/-0   
App.svelte
Main application component for hooks wizard                           
+264/-0 
HooksControls.svelte
Comprehensive hooks configuration controls interface         
+172/-0 
InfoSection.svelte
Contract information configuration section                             
+32/-0   
cairo.html
Add uniswap-hooks navigation link                                               
+1/-0     
index.html
Add uniswap-hooks navigation link                                               
+1/-0     
stellar.html
Add uniswap-hooks navigation link                                               
+1/-0     
stylus.html
Add uniswap-hooks navigation link                                               
+1/-0     
Configuration changes
2 files
version.ts
Version compatibility configuration                                           
+4/-0     
highlightjs.ts
Configure syntax highlighting for hooks                                   
+7/-0     
Additional files
11 files
package.json +1/-0     
CHANGELOG.md +6/-0     
LICENSE +661/-0 
NOTICE +8/-0     
README.md +1/-0     
ava.config.js +9/-0     
package.json +36/-0   
tsconfig.json +16/-0   
uniswap-hooks.html +87/-0   
vars.css +2/-0     
standalone.css +4/-0     

@qodo-merge-pro
Copy link

PR Reviewer Guide 🔍

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Possible Issue

The new using-handling (addUsing) is added in the builder and printing, but the Contract interface only shows using: Using[] without any new type definition in this diff. Verify that the Using type and initialization of this.using are correctly declared/initialized to avoid runtime errors and type mismatches, and ensure addUsing is wired in ContractBuilder constructor.

  using: Using[];
  imports: ImportContract[];
  functions: ContractFunction[];
  constructorCode: string[];
  constructorArgs: FunctionArgument[];
  variables: string[];
  upgradeable: boolean;
}

export type Value = string | number | { lit: string } | { note: string; value: Value };

export interface Parent {
  contract: ImportContract;
  params: Value[];
  importOnly?: boolean;
}

export interface ImportContract extends ReferencedContract {
  path: string;
}

export interface ReferencedContract {
  name: string;
  transpiled?: boolean;
}

export interface Using {
  library: ImportContract;
  usingFor: string;
}

export interface BaseFunction {
  name: string;
  args: FunctionArgument[];
  returns?: string[];
  kind: FunctionKind;
  mutability?: FunctionMutability;
}

export interface ContractFunction extends BaseFunction {
  override: Set<ReferencedContract>;
  modifiers: string[];
  code: string[];
  mutability: FunctionMutability;
  final: boolean;
  comments: string[];
}

export type FunctionKind = 'internal' | 'public';
export type FunctionMutability = (typeof mutabilityRank)[number];

// Order is important
const mutabilityRank = ['pure', 'view', 'nonpayable', 'payable'] as const;

function maxMutability(a: FunctionMutability, b: FunctionMutability): FunctionMutability {
  return mutabilityRank[Math.max(mutabilityRank.indexOf(a), mutabilityRank.indexOf(b))]!;
}

export interface FunctionArgument {
  type: string | ReferencedContract;
  name: string;
}

export interface NatspecTag {
  key: string;
  value: string;
}

export class ContractBuilder implements Contract {
  readonly name: string;
  license: string = 'MIT';
  upgradeable = false;

  readonly using: Using[] = [];
  readonly natspecTags: NatspecTag[] = [];

  readonly constructorArgs: FunctionArgument[] = [];
  readonly constructorCode: string[] = [];
  readonly variableSet: Set<string> = new Set();

  private parentMap: Map<string, Parent> = new Map<string, Parent>();
  private functionMap: Map<string, ContractFunction> = new Map();

  constructor(name: string) {
    this.name = toIdentifier(name, true);
  }

  get parents(): Parent[] {
    return [...this.parentMap.values()]
      .filter(p => !p.importOnly)
      .sort((a, b) => {
        if (a.contract.name === 'Initializable') {
          return -1;
        } else if (b.contract.name === 'Initializable') {
          return 1;
        } else {
          return 0;
        }
      });
  }

  get imports(): ImportContract[] {
    return [...[...this.parentMap.values()].map(p => p.contract), ...this.using.map(u => u.library)];
  }

  get functions(): ContractFunction[] {
    return [...this.functionMap.values()];
  }

  get variables(): string[] {
    return [...this.variableSet];
  }

  addParent(contract: ImportContract, params: Value[] = []): boolean {
    const present = this.parentMap.has(contract.name);
    this.parentMap.set(contract.name, { contract, params });
    return !present;
  }

  addImportOnly(contract: ImportContract): boolean {
    const present = this.parentMap.has(contract.name);
    this.parentMap.set(contract.name, {
      contract,
      params: [],
      importOnly: true,
    });
    return !present;
  }

  addUsing(library: ImportContract, usingFor: string): boolean {
    const exists = this.using.some(u => u.library.name === library.name && u.usingFor === usingFor);
    if (!exists) {
      this.using.push({ library, usingFor });
      return true;
    }
    return false;
  }
Logic Error

sanitizeKind lowercases and uppercases only the first character, which turns most strings into a single capital letter (e.g., "uniswap-hooks" -> "U"), then isKind only accepts "Hooks". This effectively collapses any input into "Hooks" except the exact "Hooks". Confirm intended behavior or adjust to properly normalize full strings.

export function sanitizeKind(kind: unknown): Kind {
  if (typeof kind === 'string') {
    const sanitized = kind.trim().toLowerCase().charAt(0).toUpperCase();
    if (isKind(sanitized)) {
      return sanitized;
    }
  }
  return 'Hooks';
}

function isKind<T>(value: Kind | T): value is Kind {
  switch (value) {
    case 'Hooks':
      return true;

    default: {
      // Static assert that we've checked all kinds.
      const _: T = value;
      return false;
    }
  }
}
Incorrect Docs

Help tooltips for several options are placeholders or incorrect (e.g., ERC6909 described as non-fungible, Pausable text repeated across various unrelated features). Update copy and links to accurate docs to avoid user confusion.

  <div class="checkbox-group">
    {#each ALL_HOOKS.slice(0, 4) as hookName}
        <label class:checked={opts.hook === hookName}>
          <input type="radio" bind:group={opts.hook} value={hookName} />
          {hookName}
          <HelpTooltip link="https://docs.openzeppelin.com/contracts/api/utils#Pausable">
            @TBD Privileged accounts will be able to pause the functionality marked as <code>whenNotPaused</code>. Useful for
            emergency response.
          </HelpTooltip>
        </label>
    {/each}
  </div>

</section>

<section class="controls-section">
  <h1>Fee Hooks</h1>

  <div class="checkbox-group">
    {#each ALL_HOOKS.slice(4, 8) as hookName}
        <label class:checked={opts.hook === hookName}>
          <input type="radio" bind:group={opts.hook} value={hookName} />
          {hookName}
          <HelpTooltip link="https://docs.openzeppelin.com/contracts/api/utils#Pausable">
            @TBD Privileged accounts will be able to pause the functionality marked as <code>whenNotPaused</code>. Useful for
            emergency response.
          </HelpTooltip>
        </label>
    {/each}
  </div>

</section>

<section class="controls-section">
  <h1>General Hooks</h1>

  <div class="checkbox-group">
    {#each ALL_HOOKS.slice(8) as hookName}
        <label class:checked={opts.hook === hookName}>
          <input type="radio" bind:group={opts.hook} value={hookName} />
          {hookName}
          <HelpTooltip link="https://docs.openzeppelin.com/contracts/api/utils#Pausable">
            @TBD Privileged accounts will be able to pause the functionality marked as <code>whenNotPaused</code>. Useful for
            emergency response.
          </HelpTooltip>
        </label>
    {/each}
  </div>

</section>

<section class="controls-section">
  <h1>Features</h1>

  <div class="checkbox-group">
    <label class:checked={opts.pausable}>
      <input type="checkbox" bind:checked={opts.pausable} />
      Pausable
      <HelpTooltip link="https://docs.openzeppelin.com/contracts/api/utils#Pausable">
        Privileged accounts will be able to pause the functionality marked as <code>whenNotPaused</code>. Useful for
        emergency response.
      </HelpTooltip>
    </label>
  </div>
</section>

<ExpandableToggleRadio
  label="Shares"
  bind:value={opts.shares.options}
  defaultValue="ERC20"
  helpContent="Use ERC20 or ERC6909 to represent shares of a pool."
  helpLink="https://docs.openzeppelin.com/contracts/api/token/erc20"
>
  <div class="checkbox-group">
    <label class:checked={opts.shares.options === 'ERC20'}>
      <input type="radio" bind:group={opts.shares.options} value="ERC20" />
      ERC-20
      <HelpTooltip link="https://docs.openzeppelin.com/contracts/api/token/erc20">
        ERC-20 is the standard for fungible tokens.
      </HelpTooltip>
    </label>

    <label class:checked={opts.shares.options === 'ERC6909'}>
      <input type="radio" bind:group={opts.shares.options} value="ERC6909" />
      ERC-6909
      <HelpTooltip link="https://docs.openzeppelin.com/contracts/api/token/erc6909">
        ERC-6909 is a standard for non-fungible tokens.
      </HelpTooltip>
    </label>
  </div>
  <div style="height: 0.5rem;"></div>
  <div class="grid grid-cols-[2fr,1fr] gap-2">
    <label class="labeled-input">
      <span>Name</span>
      <input bind:value={opts.shares.name} />
    </label>

    <label class="labeled-input">
      <span>Symbol</span>
      <input bind:value={opts.shares.symbol} />
    </label>
  </div>
</ExpandableToggleRadio>

<AccessControlSection bind:access={opts.access} required={requireAccessControl} />

<section class="controls-section">
  <h1>Utilities</h1>

  <div class="checkbox-group">
    <label class:checked={opts.currencySettler}>
      <input type="checkbox" bind:checked={opts.currencySettler} />
      CurrencySettler
      <HelpTooltip link="https://docs.openzeppelin.com/contracts/api/utils#Pausable">
        @TBD Privileged accounts will be able to pause the functionality marked as <code>whenNotPaused</code>. Useful for
        emergency response.
      </HelpTooltip>
    </label>

    <label class:checked={opts.safeCast}>
      <input type="checkbox" bind:checked={opts.safeCast} />
      SafeCast
      <HelpTooltip link="https://docs.openzeppelin.com/contracts/api/utils#Pausable">
        @TBD Privileged accounts will be able to pause the functionality marked as <code>whenNotPaused</code>. Useful for
        emergency response.
      </HelpTooltip>
    </label>

    <label class:checked={opts.transientStorage}>
      <input type="checkbox" bind:checked={opts.transientStorage} />
      Transient Storage
      <HelpTooltip link="https://docs.openzeppelin.com/contracts/api/utils#Pausable">
        @TBD Privileged accounts will be able to pause the functionality marked as <code>whenNotPaused</code>. Useful for
        emergency response.
      </HelpTooltip>
    </label>
  </div>
</section>

@gonzaotc
Copy link
Contributor Author

I confirm that I have read and hereby agree to the OpenZeppelin Contributor License Agreement

@qodo-merge-pro
Copy link

qodo-merge-pro bot commented Aug 13, 2025

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Missing core dependency integration

The new Uniswap Hooks package relies on @uniswap/v4-core types (e.g.,
IPoolManager) but the repo only adds @openzeppelin/uniswap-hooks; there is no
declared dependency on Uniswap v4 core or pinning of versions, risking broken
imports and incompatibilities. Add explicit, version-pinned dependencies (and
peer ranges if appropriate) for @uniswap/v4-core and any other required Uniswap
packages, and update the compatibleContractsSemver from '^0.0.0' to a meaningful
range to enforce UI compatibility checks.

Examples:

packages/core/uniswap-hooks/src/hooks.ts [132-135]
c.addImportOnly({
  name: 'IPoolManager',
  path: `@uniswap/v4-core/contracts/interfaces/IPoolManager.sol`,
});
packages/core/uniswap-hooks/package.json [23-26]
"devDependencies": {
  "@openzeppelin/uniswap-hooks": "https://github.com/OpenZeppelin/uniswap-hooks",
  "@openzeppelin/contracts": "^5.3.0",
  "@types/node": "^20.0.0",

Solution Walkthrough:

Before:

// packages/core/uniswap-hooks/package.json
"devDependencies": {
  "@openzeppelin/uniswap-hooks": "...",
  "@openzeppelin/contracts": "...",
  // Missing @uniswap/v4-core
}

// packages/core/uniswap-hooks/src/utils/version.ts
export const compatibleContractsSemver = '^0.0.0';

After:

// packages/core/uniswap-hooks/package.json
"dependencies": {
  "@uniswap/v4-core": "^1.0.0" // Or appropriate version
},
"devDependencies": {
  "@openzeppelin/uniswap-hooks": "...",
  "@openzeppelin/contracts": "...",
}

// packages/core/uniswap-hooks/src/utils/version.ts
export const compatibleContractsSemver = '^1.0.0';
Suggestion importance[1-10]: 9

__

Why: This suggestion correctly identifies a critical packaging flaw where a required dependency @uniswap/v4-core is used but not declared, which would break the package for consumers.

High
Possible issue
Add library to imports automatically

The addUsing method should also add the library to imports to ensure it's
properly imported in the generated contract. Without this, the library may be
referenced but not imported, causing compilation errors.

packages/core/solidity/src/contract.ts [137-144]

 addUsing(library: ImportContract, usingFor: string): boolean {
   const exists = this.using.some(u => u.library.name === library.name && u.usingFor === usingFor);
   if (!exists) {
     this.using.push({ library, usingFor });
+    this.addImportOnly(library);
     return true;
   }
   return false;
 }
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: This is a critical bug fix, as using for statements require the library to be imported, and without this change, the generated code would fail to compile.

High
Fix string capitalization logic

The sanitization logic is incorrect - it only takes the first character and
uppercases it, which will always result in a single character like "H". This
should properly capitalize the entire string to match the expected "Hooks"
format.

packages/core/uniswap-hooks/src/kind.ts [5-13]

 export function sanitizeKind(kind: unknown): Kind {
   if (typeof kind === 'string') {
-    const sanitized = kind.trim().toLowerCase().charAt(0).toUpperCase();
-    if (isKind(sanitized)) {
-      return sanitized;
+    const sanitized = kind.trim().toLowerCase();
+    const capitalized = sanitized.charAt(0).toUpperCase() + sanitized.slice(1);
+    if (isKind(capitalized)) {
+      return capitalized;
     }
   }
   return 'Hooks';
 }
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: This is a critical bug fix for the sanitizeKind function, as the original logic was incorrect and would always return the default value 'Hooks' instead of the sanitized input.

High
Possible issue
Fix library name interpolation

The transformName helper returns a transformed import contract, not the string
name. Interpolating it directly will produce [object Object] in output. Extract
and use the transformed name property (or stringify appropriately) to avoid
invalid Solidity.

packages/core/solidity/src/print.ts [279]

-return entries.map(u => `using ${transformName(u.library)} for ${u.usingFor};`);
+return entries.map(u => {
+  const lib = transformName(u.library);
+  const libName = typeof lib === 'string' ? lib : lib.name;
+  return `using ${libName} for ${u.usingFor};`;
+});
  • Apply / Chat
Suggestion importance[1-10]: 9

__

Why: This suggestion correctly identifies a bug where an object would be interpolated into a string, leading to invalid Solidity code using [object Object].... The fix is crucial for the new using statement printing functionality to work correctly.

High
General
Correct ERC-6909 description

ERC-6909 is a multi-token (fungible) standard, not non-fungible. Correct the
tooltip text to avoid misleading users configuring shares.

packages/ui/src/uniswap-hooks/HooksControls.svelte [118-120]

 <HelpTooltip link="https://docs.openzeppelin.com/contracts/api/token/erc6909">
-  ERC-6909 is a standard for non-fungible tokens.
+  ERC-6909 is a standard for multi-token fungible ledgers.
 </HelpTooltip>

[Suggestion processed]

Suggestion importance[1-10]: 6

__

Why: The suggestion corrects a misleading description of the ERC-6909 standard in a UI tooltip, which improves user understanding and prevents potential misconfiguration.

Low
Align default contract name

Defaulting the generated contract name to "MyToken" is inconsistent with the
Hooks flow where the default is "MyHook". Use the same default to match UI
labels and avoid confusion in Remix/code output.

packages/ui/src/uniswap-hooks/App.svelte [49]

-let contract: Contract = new ContractBuilder(initialOpts.name ?? 'MyToken');
+let contract: Contract = new ContractBuilder(initialOpts.name ?? 'MyHook');

[Suggestion processed]

Suggestion importance[1-10]: 5

__

Why: This suggestion improves UI consistency by aligning the default contract name in the code generation logic with the default name used in the UI controls, reducing potential user confusion.

Low
  • More

@socket-security
Copy link

socket-security bot commented Aug 13, 2025

All alerts resolved. Learn more about Socket for GitHub.

This PR previously contained dependency changes with security issues that have been resolved, removed, or ignored.

Ignoring alerts on:

  • css-tree@1.1.3
  • estraverse@5.3.0
  • dotenv@8.6.0
  • ajv@6.12.6
  • imurmurhash@0.1.4
  • json-stable-stringify-without-jsonify@1.0.1
  • natural-compare@1.4.0
  • fast-json-stable-stringify@2.1.0
  • json-schema-traverse@0.4.1
  • uri-js@4.4.1
  • esrecurse@4.3.0
  • acorn-jsx@5.3.2
  • parent-module@1.0.1
  • resolve-from@4.0.0
  • external-editor@3.1.0
  • chardet@0.7.0
  • callsites@3.1.0
  • p-try@2.2.0
  • lines-and-columns@1.2.4
  • is-windows@1.0.2
  • globby@11.1.0
  • node-fetch@2.7.0
  • object-assign@4.1.1
  • json-buffer@3.0.1
  • whatwg-url@5.0.0
  • tr46@0.0.3
  • webidl-conversions@3.0.1
  • on-finished@2.4.1
  • yargs@17.7.2
  • cliui@8.0.1
  • yargs-parser@21.1.1
  • ee-first@1.1.1
  • eslint-visitor-keys@3.4.3
  • better-path-resolve@1.0.0
  • keyv@4.5.4
  • @humanwhocodes/module-importer@1.0.1
  • @manypkg/find-root@1.1.0
  • @types/node@12.20.55
  • @manypkg/get-packages@1.1.3
  • any-promise@1.3.0
  • boolbase@1.0.0
  • domhandler@5.0.3
  • content-type@1.0.5
  • cssesc@3.0.0
  • detect-indent@6.1.0
  • domelementtype@2.3.0
  • domhandler@4.3.1
  • iconv-lite@0.6.3
  • escape-html@1.0.3
  • glob-parent@6.0.2
  • levn@0.4.1
  • prelude-ls@1.2.1
  • type-check@0.4.0
  • etag@1.8.1
  • extendable-error@0.1.7
  • graphemer@1.4.0
  • icss-utils@5.1.0
  • is-subdir@1.2.0
  • lodash.merge@4.6.2
  • lodash.startcase@4.4.0
  • min-indent@1.0.1
  • mri@1.2.0
  • nth-check@2.1.1
  • outdent@0.5.0
  • p-filter@2.1.0
  • p-map@2.1.0
  • parseurl@1.3.3
  • postcss-value-parser@4.2.0
  • range-parser@1.2.1
  • read-yaml-file@1.1.0
  • sade@1.8.1
  • strip-bom@3.0.0
  • term-size@2.2.1
  • vary@1.1.2
  • yaml@1.10.2
  • prettier-linter-helpers@1.0.0
  • fast-diff@1.3.0
  • colord@2.9.3
  • estree-walker@2.0.2
  • pluralize@8.0.0
  • cors@2.8.5
  • tree-kill@1.2.2
  • caniuse-api@3.0.0
  • cssnano-utils@3.1.0
  • indent-string@5.0.0
  • strip-indent@4.0.0
  • is-promise@4.0.0
  • media-typer@1.1.0
  • clean-regexp@1.0.0
  • regexp-tree@0.1.27
  • dataloader@1.4.0
  • punycode@2.3.1
  • @types/json-schema@7.0.15
  • @changesets/errors@0.2.0
  • @changesets/get-github-info@0.6.0
  • @changesets/get-version-range-type@0.4.0
  • file-entry-cache@8.0.0
  • human-id@4.1.1
  • globals@14.0.0
  • flat-cache@4.0.1
  • encodeurl@2.0.0
  • change-case@5.4.4
  • svelte-preprocess@5.1.4
  • optionator@0.9.4
  • postcss-load-config@6.0.1
  • esquery@1.6.0
  • raw-body@3.0.0
  • rimraf@5.0.10
  • postcss-selector-parser@6.1.2
  • negotiator@1.0.0
  • @changesets/logger@0.1.1
  • fresh@2.0.0
  • source-map-js@1.2.1
  • accepts@2.0.0
  • content-disposition@1.0.0
  • @humanwhocodes/retry@0.3.1
  • cookie@0.7.2
  • @eslint-community/regexpp@4.12.1
  • @humanfs/node@0.16.6
  • @humanfs/core@0.19.1
  • cookie-signature@1.2.2
  • regjsparser@0.12.0
  • tslib@2.8.1
  • undici-types@6.21.0
  • spawndamnit@3.0.1
  • lilconfig@3.1.3
  • node-releases@2.0.19
  • side-channel-map@1.0.1
  • side-channel-list@1.0.0
  • side-channel-weakmap@1.0.2
  • jsesc@3.1.0
  • side-channel@1.1.0
  • magic-string@0.30.17
  • resolve@1.22.10
  • qs@6.14.0
  • @eslint/object-schema@2.1.6
  • import-fresh@3.3.1
  • object-inspect@1.13.4
  • postcss-selector-parser@7.1.0
  • @changesets/changelog-git@0.2.1
  • @changesets/get-dependents-graph@2.1.3
  • @changesets/pre@2.0.2
  • @changesets/should-skip-package@0.1.2
  • @changesets/types@6.1.0
  • @changesets/write@0.4.0
  • @changesets/parse@0.4.1
  • @changesets/changelog-github@0.5.1
  • flatted@3.3.3
  • @changesets/config@3.1.1
  • rxjs@7.8.2
  • update-browserslist-db@1.1.3
  • builtin-modules@5.0.0
  • is-builtin-module@5.0.0
  • find-up-simple@1.0.1
  • package-manager-detector@0.2.11
  • finalhandler@2.1.0
  • mime-db@1.54.0
  • quansync@0.2.10
  • ts-api-utils@2.1.0
  • @eslint/eslintrc@3.3.1
  • @types/semver@7.7.0
  • mime-types@3.0.1
  • type-is@2.0.1
  • body-parser@2.2.0
  • send@1.2.0
  • express@5.1.0
  • @changesets/apply-release-plan@7.0.12
  • @changesets/git@3.0.4
  • @changesets/read@0.6.5
  • @babel/helper-validator-identifier@7.27.1
  • @babel/code-frame@7.27.1
  • @eslint-community/eslint-utils@4.7.0
  • cssnano-utils@5.0.1
  • eventsource@3.0.7
  • prettier-plugin-svelte@3.4.0
  • shell-quote@1.8.3
  • @types/estree@1.0.8
  • statuses@2.0.2
  • eslint-scope@8.4.0
  • espree@10.4.0
  • postcss@8.5.6
  • @rollup/pluginutils@5.2.0
  • @changesets/assemble-release-plan@6.0.9
  • @changesets/cli@2.29.5
  • @changesets/get-release-plan@4.0.13
  • concurrently@9.2.0
  • eventsource-parser@3.0.3
  • @eslint/config-array@0.21.0
  • prettier@3.6.2
  • css-what@6.2.2
  • ci-info@4.3.0
  • ava@6.4.1
  • eslint-config-prettier@10.1.8
  • @pkgr/core@0.2.9
  • synckit@0.11.11
  • core-js-compat@3.45.0
  • eslint-plugin-prettier@5.5.4
  • @eslint/config-helpers@0.3.1
  • @eslint/core@0.15.2
  • @eslint/plugin-kit@0.3.5
  • @types/node@20.19.10
  • @eslint/js@9.33.0
  • eslint@9.33.0
  • browserslist@4.25.2
  • @typescript-eslint/tsconfig-utils@8.39.1
  • @typescript-eslint/eslint-plugin@8.39.1
  • @typescript-eslint/scope-manager@8.39.1
  • @typescript-eslint/type-utils@8.39.1
  • @typescript-eslint/utils@8.39.1
  • @typescript-eslint/visitor-keys@8.39.1
  • @typescript-eslint/types@8.39.1
  • @typescript-eslint/typescript-estree@8.39.1
  • @typescript-eslint/project-service@8.39.1
  • @typescript-eslint/parser@8.39.1
  • typescript-eslint@8.39.1
  • @jridgewell/gen-mapping@0.3.13
  • @jridgewell/trace-mapping@0.3.30
  • caniuse-lite@1.0.30001735
  • @babel/runtime@7.28.3
  • @modelcontextprotocol/sdk@1.17.3
  • electron-to-chromium@1.5.201
  • eslint-plugin-unicorn@61.0.2
  • @openzeppelin/uniswap-hooks@1.2.0

View full report

@gonzaotc gonzaotc changed the title Hooks Wizard v1 [WIP] Hooks Wizard v0.0.0 [WIP] Aug 13, 2025
@gonzaotc gonzaotc changed the title Hooks Wizard v0.0.0 [WIP] Hooks Wizard v0.0.1 Oct 20, 2025
@CoveMB CoveMB requested a review from a team as a code owner October 21, 2025 00:47
Copy link
Contributor

@CoveMB CoveMB left a comment

Choose a reason for hiding this comment

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

Nice work!
I am thinking maybe there could be a compile test for each of hook's basic configuration?

Copy link
Member

@ericglau ericglau left a comment

Choose a reason for hiding this comment

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

LGTM!

Reminder when Uniswap Hooks 1.2.0 is released:

  • Update devDependencies in packages/core/uniswap-hooks/package.json
  • Update UI hyperlink injection to point to v1.2.0 tag

@gonzaotc gonzaotc requested a review from CoveMB October 22, 2025 20:30
@ericglau
Copy link
Member

@SocketSecurity ignore-all
Looks like AI-detected false positives

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.

3 participants