Skip to content

Instantly share code, notes, and snippets.

@Munsterberg
Created January 19, 2026 21:24
Show Gist options
  • Select an option

  • Save Munsterberg/b4c98e46b8d6811f2bdebe785e140a65 to your computer and use it in GitHub Desktop.

Select an option

Save Munsterberg/b4c98e46b8d6811f2bdebe785e140a65 to your computer and use it in GitHub Desktop.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;
import {BaseHook} from "v4-periphery/utils/BaseHook.sol";
import {IPoolManager} from "@uniswap/v4-core/src/interfaces/IPoolManager.sol";
import {Hooks} from "@uniswap/v4-core/src/libraries/Hooks.sol";
import {PoolKey} from "@uniswap/v4-core/src/types/PoolKey.sol";
import {BeforeSwapDelta, BeforeSwapDeltaLibrary} from "@uniswap/v4-core/src/types/BeforeSwapDelta.sol";
import {PoolId, PoolIdLibrary} from "@uniswap/v4-core/src/types/PoolId.sol";
import {BalanceDelta} from "@uniswap/v4-core/src/types/BalanceDelta.sol";
/**
* @title AquinasPoolHook
* @notice Uniswap V4 hook for all Aquinas DAOs
* @dev Uses authorization registry to prevent any frontrunning the LP
*/
contract AquinasPoolHook is BaseHook {
using PoolIdLibrary for PoolKey;
/// @notice The Aquinas factory that can authorize pool initializers
address public immutable factory;
/// @notice Maps poolId => authorized Safe address that can initialize this pool
mapping(PoolId => address) public authorizedInitializers;
/// @notice Tracks which pools have been initialized
mapping(PoolId => bool) public initialized;
event PoolInitializerAuthorized(PoolId indexed poolId, address indexed safe, PoolKey poolKey);
event PoolInitialized(PoolId indexed poolId, address indexed safe);
error OnlyFactory();
error AlreadyAuthorized();
error UnauthorizedInitializer();
error AlreadyInitialized();
constructor(IPoolManager _poolManager, address _factory) BaseHook(_poolManager) {
// NOTE: basehook checks for address(0)
factory = _factory;
}
/**
* @notice Returns the hook permissions (only beforeInitialize)
*/
function getHookPermissions() public pure override returns (Hooks.Permissions memory) {
return Hooks.Permissions({
beforeInitialize: true,
afterInitialize: false,
beforeAddLiquidity: false,
afterAddLiquidity: false,
beforeRemoveLiquidity: false,
afterRemoveLiquidity: false,
beforeSwap: false,
afterSwap: false,
beforeDonate: false,
afterDonate: false,
beforeSwapReturnDelta: false,
afterSwapReturnDelta: false,
afterAddLiquidityReturnDelta: false,
afterRemoveLiquidityReturnDelta: false
});
}
/**
* @notice Authorizes a Safe address to initialize a specific pool
* @dev Called by factory during createDAO()
* @param key The pool key for which to authorize initialization
* @param safe The Safe address that will be authorized
*/
function authorizePoolInitializer(PoolKey calldata key, address safe) external {
if (msg.sender != factory) revert OnlyFactory();
PoolId poolId = key.toId();
if (authorizedInitializers[poolId] != address(0)) revert AlreadyAuthorized();
authorizedInitializers[poolId] = safe;
emit PoolInitializerAuthorized(poolId, safe, key);
}
/**
* @notice beforeInitialize hook implementation
* @dev Verifies sender is authorized and pool not already initialized
* @param sender The address calling PoolManager.initialize() - the safee
* @param key The pool key being initialized
*/
function _beforeInitialize(address sender, PoolKey calldata key, uint160) internal override returns (bytes4) {
PoolId poolId = key.toId();
if (authorizedInitializers[poolId] != sender) revert UnauthorizedInitializer();
// Check not already initialized
if (initialized[poolId]) revert AlreadyInitialized();
initialized[poolId] = true;
emit PoolInitialized(poolId, sender);
return BaseHook.beforeInitialize.selector;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment