Skip to content

Commit

Permalink
feat: audit diff
Browse files Browse the repository at this point in the history
  • Loading branch information
dyedm1 committed Jun 3, 2024
1 parent 7c6116b commit f0a90ac
Show file tree
Hide file tree
Showing 34 changed files with 8,887 additions and 4,278 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ coverage
coverage.json
typechain

metadata/out/*
# Yarn files
yarn-error.log

Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,6 @@
[submodule "lib/v3-periphery"]
path = lib/v3-periphery
url = https://github.com/Uniswap/v3-periphery
[submodule "lib/solady"]
path = lib/solady
url = https://github.com/vectorized/solady
466 changes: 236 additions & 230 deletions contracts/CollateralTracker.sol

Large diffs are not rendered by default.

142 changes: 61 additions & 81 deletions contracts/PanopticFactory.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ pragma solidity ^0.8.18;
import {CollateralTracker} from "@contracts/CollateralTracker.sol";
import {PanopticPool} from "@contracts/PanopticPool.sol";
import {SemiFungiblePositionManager} from "@contracts/SemiFungiblePositionManager.sol";
import {IDonorNFT} from "@contracts/tokens/interfaces/IDonorNFT.sol";
import {IUniswapV3Factory} from "univ3-core/interfaces/IUniswapV3Factory.sol";
import {IUniswapV3Pool} from "univ3-core/interfaces/IUniswapV3Pool.sol";
// Inherited implementations
import {Multicall} from "@multicall/Multicall.sol";
import {Multicall} from "@base/Multicall.sol";
import {FactoryNFT} from "@base/FactoryNFT.sol";
// OpenZeppelin libraries
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
// Libraries
Expand All @@ -19,20 +19,17 @@ import {Errors} from "@libraries/Errors.sol";
import {Math} from "@libraries/Math.sol";
import {PanopticMath} from "@libraries/PanopticMath.sol";
import {SafeTransferLib} from "@libraries/SafeTransferLib.sol";
// Custom types
import {Pointer} from "@types/Pointer.sol";

/// @title Panoptic Factory which creates and registers Panoptic Pools.
/// @author Axicon Labs Limited
/// @notice Facilitates deployment of Panoptic pools.
contract PanopticFactory is Multicall {
contract PanopticFactory is FactoryNFT, Multicall {
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/

/// @notice Emitted when the ownership of the factory is transferred.
/// @param oldOwner The previous owner of the factory
/// @param newOwner The new owner of the factory
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

/// @notice Emitted when a Panoptic Pool is created.
/// @param poolAddress Address of the deployed Panoptic pool
/// @param uniswapPool Address of the underlying Uniswap V3 pool
Expand All @@ -59,22 +56,19 @@ contract PanopticFactory is Multicall {
CONSTANTS & IMMUTABLE
//////////////////////////////////////////////////////////////*/

/// @notice The Uniswap V3 factory contract to use
/// @notice The Uniswap V3 factory contract to use.
IUniswapV3Factory internal immutable UNIV3_FACTORY;

/// @notice The Semi Fungible Position Manager (SFPM) which tracks option positions across Panoptic Pools
/// @notice The Semi Fungible Position Manager (SFPM) which tracks option positions across Panoptic Pools.
SemiFungiblePositionManager internal immutable SFPM;

/// @notice Contract called to issue reward NFT to pool deployers
IDonorNFT internal immutable DONOR_NFT;

/// @notice Reference implementation of the `PanopticPool` to clone
/// @notice Reference implementation of the `PanopticPool` to clone.
address internal immutable POOL_REFERENCE;

/// @notice Reference implementation of the `CollateralTracker` to clone
/// @notice Reference implementation of the `CollateralTracker` to clone.
address internal immutable COLLATERAL_REFERENCE;

/// @notice Address of the Wrapped Ether (or other numeraire token) contract
/// @notice Address of the Wrapped Ether (or other numeraire token) contract.
address internal immutable WETH;

/// @notice An amount of `WETH` deployed when initializing the SFPM against a new AMM pool.
Expand All @@ -85,81 +79,46 @@ contract PanopticFactory is Multicall {
/// @dev Deploy 1e6 worth of tokens if not WETH.
uint256 internal constant FULL_RANGE_LIQUIDITY_AMOUNT_TOKEN = 1e6;

/// @notice The `observationCardinalityNext` to set on the Uniswap pool when a new PanopticPool is deployed
/// @notice The `observationCardinalityNext` to set on the Uniswap pool when a new PanopticPool is deployed.
uint16 internal constant CARDINALITY_INCREASE = 100;

/*//////////////////////////////////////////////////////////////
STORAGE
//////////////////////////////////////////////////////////////*/

/// @notice The owner of the Panoptic Factory
address internal s_owner;

/// @notice Whether this contract's state has been initialized
bool internal s_initialized;

/// @notice Mapping from address(UniswapV3Pool) to address(PanopticPool) that stores the address of all deployed Panoptic Pools
/// @notice Mapping from address(UniswapV3Pool) to address(PanopticPool) that stores the address of all deployed Panoptic Pools.
mapping(IUniswapV3Pool univ3pool => PanopticPool panopticPool) internal s_getPanopticPool;

/*//////////////////////////////////////////////////////////////
INITIALIZATION
//////////////////////////////////////////////////////////////*/

/// @notice Set immutable variables.
/// @notice Set immutable variables and store metadata pointers.
/// @param _WETH9 Address of the Wrapped Ether (or other numeraire token) contract
/// @param _SFPM The canonical `SemiFungiblePositionManager` deployment
/// @param _univ3Factory The canonical Uniswap V3 Factory deployment
/// @param _donorNFT The contract called to issue NFT rewards for deploying pools
/// @param _poolReference The reference implementation of the `PanopticPool` to clone
/// @param _collateralReference The reference implementation of the `CollateralTracker` to clone
/// @param properties An array of identifiers for different categories of metadata
/// @param indices A nested array of keys for K-V metadata pairs for each property in `properties`
/// @param pointers Contains pointers to the metadata values stored in contract data slices for each index in `indices`
constructor(
address _WETH9,
SemiFungiblePositionManager _SFPM,
IUniswapV3Factory _univ3Factory,
IDonorNFT _donorNFT,
address _poolReference,
address _collateralReference
) {
address _collateralReference,
bytes32[] memory properties,
uint256[][] memory indices,
Pointer[][] memory pointers
) FactoryNFT(properties, indices, pointers) {
WETH = _WETH9;
SFPM = _SFPM;
DONOR_NFT = _donorNFT;
// We store the Uniswap Factory contract - later we can use this to verify uniswap pools
UNIV3_FACTORY = _univ3Factory;
POOL_REFERENCE = _poolReference;
COLLATERAL_REFERENCE = _collateralReference;
}

/// @notice Initialize state.
/// @param _owner The first owner of `PanopticFactory`
function initialize(address _owner) public {
if (!s_initialized) {
s_owner = _owner;
s_initialized = true;
}
}

/*//////////////////////////////////////////////////////////////
ACCESS CONTROL
//////////////////////////////////////////////////////////////*/

/// @notice Set the owner of the Panoptic Factory.
/// @param newOwner The new owner of the Panoptic Factory
function transferOwnership(address newOwner) external {
address currentOwner = s_owner;

if (msg.sender != currentOwner) revert Errors.NotOwner();

s_owner = newOwner;

emit OwnershipTransferred(currentOwner, newOwner);
}

/// @notice Get the address of the owner of this Panoptic Factory.
/// @return The address which owns this Panoptic Factory
function owner() external view returns (address) {
return s_owner;
}

/*//////////////////////////////////////////////////////////////
CALLBACK HANDLERS
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -199,30 +158,27 @@ contract PanopticFactory is Multicall {
//////////////////////////////////////////////////////////////*/

/// @notice Create a new Panoptic Pool linked to the given Uniswap pool identified uniquely by the incoming parameters.
/// @dev Pool deployment is restricted to the factory owner until transferred to the zero address.
/// @dev There is a 1:1 mapping between a Panoptic Pool and a Uniswap Pool.
/// @dev A Uniswap pool is uniquely identified by its tokens and the fee.
/// @dev Salt used in PanopticPool CREATE2 is [leading 20 msg.sender chars][leading 20 pool address chars][salt].
/// @param token0 Address of token0 for the underlying Uniswap v3 pool
/// @param token1 Address of token1 for the underlying Uniswap v3 pool
/// @param fee The fee tier of the underlying Uniswap v3 pool, denominated in hundredths of bips
/// @param salt User-defined salt used in CREATE2 for the PanopticPool (must contain caller addr as first 20 bytes)
/// @param salt User-defined component of salt used in CREATE2 for the PanopticPool (must be a uint96 number)
/// @param amount0Max The maximum amount of token0 to spend on the full-range deployment, which serves as a slippage check
/// @param amount1Max The maximum amount of token1 to spend on the full-range deployment, which serves as a slippage check
/// @return newPoolContract The address of the newly deployed Panoptic pool
function deployNewPool(
address token0,
address token1,
uint24 fee,
bytes32 salt
uint96 salt,
uint256 amount0Max,
uint256 amount1Max
) external returns (PanopticPool newPoolContract) {
// sort the tokens, if necessary:
(token0, token1) = token0 < token1 ? (token0, token1) : (token1, token0);

// frontrunning protection for mined pool addresses
if (address(bytes20(salt)) != msg.sender) revert Errors.InvalidSalt();

// restrict pool deployment to owner if contract has not been made permissionless
address _owner = s_owner;
if (_owner != address(0) && _owner != msg.sender) revert Errors.NotOwner();

IUniswapV3Pool v3Pool = IUniswapV3Pool(UNIV3_FACTORY.getPool(token0, token1, fee));
if (address(v3Pool) == address(0)) revert Errors.UniswapPoolNotInitialized();

Expand All @@ -232,9 +188,18 @@ contract PanopticFactory is Multicall {
// initialize pool in SFPM if it has not already been initialized
SFPM.initializeAMMPool(token0, token1, fee);

// This creates a new Panoptic Pool (proxy to the PanopticPool implementation)
// Users can specify a salt, the aim is to incentivize the mining of addresses with leading zeros
newPoolContract = PanopticPool(POOL_REFERENCE.cloneDeterministic(salt));
// salt format: (first 20 characters of deployer address) + (first 20 characters of UniswapV3Pool) + (uint96 user supplied salt)
bytes32 salt32 = bytes32(
abi.encodePacked(
uint80(uint160(msg.sender) >> 80),
uint80(uint160(address(v3Pool)) >> 80),
salt
)
);

// This creates a new Panoptic Pool (proxy to the PanopticPool implementation)
newPoolContract = PanopticPool(POOL_REFERENCE.cloneDeterministic(salt32));

// Deploy collateral token proxies
CollateralTracker collateralTracker0 = CollateralTracker(
Expand Down Expand Up @@ -262,8 +227,11 @@ contract PanopticFactory is Multicall {
// The SFPM will `safeTransferFrom` tokens from the donor during the mint callback
(uint256 amount0, uint256 amount1) = _mintFullRange(v3Pool, token0, token1, fee);

if (amount0 > amount0Max || amount1 > amount1Max) revert Errors.PriceBoundFail();

// Issue reward NFT to donor
DONOR_NFT.issueNFT(msg.sender, newPoolContract, token0, token1, fee);
uint256 tokenId = uint256(uint160(address(newPoolContract)));
_mint(msg.sender, tokenId);

emit PoolDeployed(
newPoolContract,
Expand All @@ -282,16 +250,20 @@ contract PanopticFactory is Multicall {
/// @notice Find the salt which would give a Panoptic Pool the highest rarity within the search parameters.
/// @dev The rarity is defined in terms of how many leading zeros the Panoptic pool address has.
/// @dev Note that the final salt may overflow if too many loops are given relative to the amount in `salt`.
/// @param salt Salt value ([160-bit deployer address][96-bit nonce]) to start from, useful as a checkpoint across multiple calls
/// @param deployerAddress Address of the account that deploys the new PanopticPool
/// @param v3Pool Address of the underlying UniswapV3Pool
/// @param salt Salt value ([96-bit nonce]) to start from, useful as a checkpoint across multiple calls
/// @param loops The number of mining operations starting from 'salt' in trying to find the highest rarity
/// @param minTargetRarity The minimum target rarity to mine for. The internal loop stops when this is reached *or* when no more iterations
/// @return bestSalt The salt of the rarest pool (potentially at the specified minimum target)
/// @return highestRarity The rarity of `bestSalt`
function minePoolAddress(
bytes32 salt,
address deployerAddress,
address v3Pool,
uint96 salt,
uint256 loops,
uint256 minTargetRarity
) external view returns (bytes32 bestSalt, uint256 highestRarity) {
) external view returns (uint96 bestSalt, uint256 highestRarity) {
// Start at the given 'salt' value (a checkpoint used to continue mining across multiple calls)

// Runs until 'bestSalt' reaches 'minTargetRarity' or for 'loops', whichever comes first
Expand All @@ -301,8 +273,16 @@ contract PanopticFactory is Multicall {
}

for (; uint256(salt) < maxSalt; ) {
bytes32 newSalt = bytes32(
abi.encodePacked(
uint80(uint160(deployerAddress) >> 80),
uint80(uint160(v3Pool) >> 80),
salt
)
);

uint256 rarity = PanopticMath.numberOfLeadingHexZeros(
POOL_REFERENCE.predictDeterministicAddress(salt)
POOL_REFERENCE.predictDeterministicAddress(newSalt)
);

if (rarity > highestRarity) {
Expand All @@ -320,7 +300,7 @@ contract PanopticFactory is Multicall {

unchecked {
// increment the nonce of `currentSalt` (lower 96 bits)
salt = bytes32(uint256(salt) + 1);
salt += 1;
}
}
}
Expand Down Expand Up @@ -416,7 +396,7 @@ contract PanopticFactory is Multicall {

/// @notice Return the address of the Panoptic Pool associated with 'univ3pool'.
/// @param univ3pool The Uniswap V3 pool address to query
/// @return Address of the Panoptic Pool associated with 'univ3pool'.
/// @return Address of the Panoptic Pool associated with 'univ3pool'
function getPanopticPool(IUniswapV3Pool univ3pool) external view returns (PanopticPool) {
return s_getPanopticPool[univ3pool];
}
Expand Down
Loading

0 comments on commit f0a90ac

Please sign in to comment.