Skip to main content

PanopticMath

Git Source

Title: Compute general math quantities relevant to Panoptic and AMM pool management.

Author: Axicon Labs Limited

Contains Panoptic-specific helpers and math functions.

State Variables
​

MAX_UINT256
​

This is equivalent to type(uint256).max β€” used in assembly blocks as a replacement.

uint256 internal constant MAX_UINT256 = 2 ** 256 - 1

TICKSPACING_VEGOID_MASK
​

Masks 16-bit tickSpacing and 8 bits of vegoid out of 64-bit [16-bit tickspacing][8-bit vegoid][40-bit poolPattern] format poolId.

uint64 internal constant TICKSPACING_VEGOID_MASK = 0xFFFFFF0000000000

PRIME_MODULUS_248
​

uint256 internal constant PRIME_MODULUS_248 = 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff13

PRIME_MODULUS_124_0
​

uint256 internal constant PRIME_MODULUS_124_0 = 0xfffffffffffffffffffffffffffffc5

PRIME_MODULUS_124_1
​

uint256 internal constant PRIME_MODULUS_124_1 = 0xffffffffffffffffffffffffffffd99

LANE_MASK_124
​

uint256 internal constant LANE_MASK_124 = 0xfffffffffffffffffffffffffffffff

UPPER_120BITS_MASK
​

uint256 internal constant UPPER_120BITS_MASK = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000

BITMASK_UINT88
​

uint256 internal constant BITMASK_UINT88 = 0xFFFFFFFFFFFFFFFFFFFFFF

BITMASK_UINT22
​

uint256 internal constant BITMASK_UINT22 = 0x3FFFFF

Functions
​

incrementPoolPattern
​

Increments the pool pattern (first 48 bits) of a poolId by 1.

function incrementPoolPattern(uint64 poolId) internal pure returns (uint64);

Parameters

NameTypeDescription
poolIduint64The 64-bit pool ID

Returns

NameTypeDescription
<none>uint64The provided poolId with its pool pattern slot incremented by 1

numberOfLeadingHexZeros
​

Get the number of leading hex characters in an address.

function numberOfLeadingHexZeros(address addr) external pure returns (uint256);

Parameters

NameTypeDescription
addraddressThe address to get the number of leading zero hex characters for

Returns

NameTypeDescription
<none>uint256The number of leading zero hex characters in the address

safeERC20Symbol
​

Returns ERC20 symbol of token.

function safeERC20Symbol(address token) external view returns (string memory);

Parameters

NameTypeDescription
tokenaddressThe address of the token to get the symbol of

Returns

NameTypeDescription
<none>stringThe symbol of token or "???" if not supported

uniswapFeeToString
​

Converts fee to a string with "bps" appended.

The lowest supported value of fee is 1 (="0.01bps").

function uniswapFeeToString(uint24 fee) internal pure returns (string memory);

Parameters

NameTypeDescription
feeuint24The fee to convert to a string (in hundredths of basis points)

Returns

NameTypeDescription
<none>stringStringified version of fee with "bps" appended

updatePositionsHash
​

Update an existing account's "positions hash" with a new tokenId.

The positions hash contains a fingerprint of all open positions created by an account/user and a count of the legs across those positions.

The "fingerprint" portion of the hash is given by XORing the hashed tokenId of each position the user has open together.

function updatePositionsHash(uint256 existingHash, TokenId tokenId, bool addFlag) internal pure returns (uint256);

Parameters

NameTypeDescription
existingHashuint256The existing position hash representing a list of positions and the count of the legs across those positions
tokenIdTokenIdThe new position to modify the existing hash with: existingHash = uint248(existingHash) ^ uint248(hashOf(tokenId))
addFlagboolWhether to mint (add) the tokenId to the count of positions or burn (subtract) it from the count (existingHash >> 248) +/- tokenId.countLegs()

Returns

NameTypeDescription
<none>uint256newHash The updated position hash with the new tokenId XORed in and the leg count incremented/decremented

homomorphicHash
​

Computes a homomorphic hash by adding or subtracting an item from an existing hash

Uses XOR-based homomorphic hashing (XHASH). The hash of the item is XORed with the existing hash. Since XOR is its own inverse (A βŠ• B βŠ• B = A), both addition and subtraction operations use the same XOR operation. This ensures the operation is reversible and order-independent for the same set of items. OR Uses additive homomorphic hashing (AdHash) over a 248-bit prime field. The hash of the item is either added to or subtracted from the existing hash using modular arithmetic. Subtraction is implemented as addition of the modular inverse: hash + (PRIME - itemHash) mod PRIME. This ensures the operation is reversible and order-independent for the same set of items. OR Uses LtHash (Lattice-based Hash) with k=2 lanes for improved collision resistance. The 248-bit hash space is divided into two 124-bit lanes, each operating under modular arithmetic with a 124-bit prime. The item hash is split into two 124-bit chunks and each chunk is added/subtracted from its corresponding lane independently. Subtraction is implemented as addition of the modular inverse: lane + (PRIME - chunk) mod PRIME. This parallel lane approach provides better security properties than single-lane hashing while maintaining homomorphic properties (order-independence and reversibility).

function homomorphicHash(uint256 hash, uint256 item, bool addFlag) internal pure returns (uint256);

Parameters

NameTypeDescription
hashuint256The existing hash value (only lower 248 bits are used)
itemuint256The item to be hashed and added/subtracted (typically a TokenId cast to uint256)
addFlagboolTrue to add the item to the hash, false to subtract it

Returns

NameTypeDescription
<none>uint256The updated homomorphic hash as a uint256 (but only lower 248 bits contain the hash)

hasNoDuplicateTokenIds
​

Checks if an array of TokenIds contains any duplicate values

Uses assembly for gas optimization. Performs O(nΒ²) comparison by checking each element against all subsequent elements. Returns false immediately upon finding the first duplicate. Arrays with 0 or 1 elements are considered to have no duplicates.

function hasNoDuplicateTokenIds(TokenId[] calldata arr) external pure returns (bool);

Parameters

NameTypeDescription
arrTokenId[]The array of TokenIds to check for duplicates

Returns

NameTypeDescription
<none>boolTrue if the array contains no duplicate TokenIds, false if duplicates are found

computeMedianObservedPrice
​

Returns the median of the last cardinality average prices over period observations from univ3pool.

Used when we need a manipulation-resistant TWAP price.

Uniswap observations snapshot the closing price of the last block before the first interaction of a given block.

The maximum frequency of observations is 1 per block, but there is no guarantee that the pool will be observed at every block.

Each period has a minimum length of blocktime * period, but may be longer if the Uniswap pool is relatively inactive.

The final price used in the array (of length cardinality) is the average of cardinality observations spaced by period (which is itself a number of observations).

Thus, the minimum total time window is cardinality * period * blocktime.

function computeMedianObservedPrice(
IUniswapV3Pool univ3pool,
uint256 observationIndex,
uint256 observationCardinality,
uint256 cardinality,
uint256 period
) internal view returns (int24, int24);

Parameters

NameTypeDescription
univ3poolIUniswapV3PoolThe Uniswap pool to get the median observation from
observationIndexuint256The index of the last observation in the pool
observationCardinalityuint256The number of observations in the pool
cardinalityuint256The number of periods to in the median price array, should be odd
perioduint256The number of observations to average to compute one entry in the median price array

Returns

NameTypeDescription
<none>int24The median of cardinality observations spaced by period in the Uniswap pool
<none>int24The latest observation in the Uniswap pool

twapFilter
​

Computes the TWAP of a Uniswap V3 pool using data from its oracle.

Note that our definition of TWAP differs from a typical mean of prices over a time window.

We instead observe the average price over a series of time intervals, and define the TWAP as the median of those averages.

function twapFilter(IUniswapV3Pool univ3pool, uint32 twapWindow) external view returns (int24);

Parameters

NameTypeDescription
univ3poolIUniswapV3PoolThe Uniswap pool from which to compute the TWAP
twapWindowuint32The time window to compute the TWAP over

Returns

NameTypeDescription
<none>int24The final calculated TWAP tick

getLiquidityChunk
​

For a given option position (tokenId), leg index within that position (legIndex), and positionSize get the tick range spanned and its liquidity (share ownership) in the Uniswap V3 pool; this is a liquidity chunk.

function getLiquidityChunk(TokenId tokenId, uint256 legIndex, uint128 positionSize)
internal
pure
returns (LiquidityChunk);

Parameters

NameTypeDescription
tokenIdTokenIdThe option position id
legIndexuint256The leg index of the option position, can be {0,1,2,3}
positionSizeuint128The number of contracts held by this leg

Returns

NameTypeDescription
<none>LiquidityChunkA LiquidityChunk with tickLower, tickUpper, and liquidity

getTicks
​

Extract the tick range specified by strike and width for the given tickSpacing.

function getTicks(int24 strike, int24 width, int24 tickSpacing) internal pure returns (int24, int24);

Parameters

NameTypeDescription
strikeint24The strike price of the option
widthint24The width of the option
tickSpacingint24The tick spacing of the underlying Uniswap V3 pool

Returns

NameTypeDescription
<none>int24The lower tick of the liquidity chunk
<none>int24The upper tick of the liquidity chunk

getRangesFromStrike
​

Returns the distances of the upper and lower ticks from the strike for a position with the given width and tickSpacing.

Given r = (width * tickSpacing) / 2, tickLower = strike - floor(r) and tickUpper = strike + ceil(r).

function getRangesFromStrike(int24 width, int24 tickSpacing) internal pure returns (int24, int24);

Parameters

NameTypeDescription
widthint24The width of the leg
tickSpacingint24The tick spacing of the underlying pool

Returns

NameTypeDescription
<none>int24The distance of the lower tick from the strike
<none>int24The distance of the upper tick from the strike

getChunkKey
​

Computes the chunk key for a given leg of a position.

The chunk key uniquely identifies a liquidity chunk by its strike, width, and token type.

function getChunkKey(TokenId tokenId, uint256 leg) internal pure returns (bytes32 chunkKey);

Parameters

NameTypeDescription
tokenIdTokenIdThe option position
leguint256The leg index within the position

Returns

NameTypeDescription
chunkKeybytes32The keccak256 hash identifying this chunk

computeExercisedAmounts
​

Compute the amount of notional value underlying an option position.

function computeExercisedAmounts(TokenId tokenId, uint128 positionSize, bool opening)
internal
pure
returns (LeftRightSigned longAmounts, LeftRightSigned shortAmounts);

Parameters

NameTypeDescription
tokenIdTokenIdThe option position id
positionSizeuint128The number of contracts of the option
openingboolWhether you need the token0s and token1s moved while opening the position, or while closing

Returns

NameTypeDescription
longAmountsLeftRightSignedLeft-right packed word where rightSlot = token0 and leftSlot = token1 held against borrowed Uniswap liquidity for long legs
shortAmountsLeftRightSignedLeft-right packed word where where rightSlot = token0 and leftSlot = token1 borrowed to create short legs

convert0to1
​

Convert an amount of token0 into an amount of token1 given the sqrtPriceX96 in a Uniswap pool defined as sqrt(1/0)*2^96.

Uses reduced precision after tick 443636 in order to accommodate the full range of ticks

function convert0to1(uint256 amount, uint160 sqrtPriceX96) internal pure returns (uint256);

Parameters

NameTypeDescription
amountuint256The amount of token0 to convert into token1
sqrtPriceX96uint160The square root of the price at which to convert amount of token0 into token1

Returns

NameTypeDescription
<none>uint256The converted amount of token0 represented in terms of token1

convert0to1RoundingUp
​

Convert an amount of token0 into an amount of token1 given the sqrtPriceX96 in a Uniswap pool defined as sqrt(1/0)*2^96.

Uses reduced precision after tick 443636 in order to accommodate the full range of ticks

function convert0to1RoundingUp(uint256 amount, uint160 sqrtPriceX96) internal pure returns (uint256);

Parameters

NameTypeDescription
amountuint256The amount of token0 to convert into token1
sqrtPriceX96uint160The square root of the price at which to convert amount of token0 into token1

Returns

NameTypeDescription
<none>uint256The converted amount of token0 represented in terms of token1

convert1to0
​

Convert an amount of token1 into an amount of token0 given the sqrtPriceX96 in a Uniswap pool defined as sqrt(1/0)*2^96.

Uses reduced precision after tick 443636 in order to accommodate the full range of ticks.

function convert1to0(uint256 amount, uint160 sqrtPriceX96) internal pure returns (uint256);

Parameters

NameTypeDescription
amountuint256The amount of token1 to convert into token0
sqrtPriceX96uint160The square root of the price at which to convert amount of token1 into token0

Returns

NameTypeDescription
<none>uint256The converted amount of token1 represented in terms of token0

convert1to0RoundingUp
​

Convert an amount of token1 into an amount of token0 given the sqrtPriceX96 in a Uniswap pool defined as sqrt(1/0)*2^96.

Uses reduced precision after tick 443636 in order to accommodate the full range of ticks.

function convert1to0RoundingUp(uint256 amount, uint160 sqrtPriceX96) internal pure returns (uint256);

Parameters

NameTypeDescription
amountuint256The amount of token1 to convert into token0
sqrtPriceX96uint160The square root of the price at which to convert amount of token1 into token0

Returns

NameTypeDescription
<none>uint256The converted amount of token1 represented in terms of token0

convert0to1
​

Convert an amount of token0 into an amount of token1 given the sqrtPriceX96 in a Uniswap pool defined as sqrt(1/0)*2^96.

Uses reduced precision after tick 443636 in order to accommodate the full range of ticks.

function convert0to1(int256 amount, uint160 sqrtPriceX96) internal pure returns (int256);

Parameters

NameTypeDescription
amountint256The amount of token0 to convert into token1
sqrtPriceX96uint160The square root of the price at which to convert amount of token0 into token1

Returns

NameTypeDescription
<none>int256The converted amount of token0 represented in terms of token1

convert0to1RoundingUp
​

Convert an amount of token0 into an amount of token1 given the sqrtPriceX96 in a Uniswap pool defined as sqrt(1/0)*2^96.

Uses reduced precision after tick 443636 in order to accommodate the full range of ticks.

function convert0to1RoundingUp(int256 amount, uint160 sqrtPriceX96) internal pure returns (int256);

Parameters

NameTypeDescription
amountint256The amount of token0 to convert into token1
sqrtPriceX96uint160The square root of the price at which to convert amount of token0 into token1

Returns

NameTypeDescription
<none>int256The converted amount of token0 represented in terms of token1

convert1to0
​

Convert an amount of token1 into an amount of token0 given the sqrtPriceX96 in a Uniswap pool defined as sqrt(1/0)*2^96.

Uses reduced precision after tick 443636 in order to accommodate the full range of ticks.

function convert1to0(int256 amount, uint160 sqrtPriceX96) internal pure returns (int256);

Parameters

NameTypeDescription
amountint256The amount of token1 to convert into token0
sqrtPriceX96uint160The square root of the price at which to convert amount of token1 into token0

Returns

NameTypeDescription
<none>int256The converted amount of token1 represented in terms of token0

convert1to0RoundingUp
​

Convert an amount of token1 into an amount of token0 given the sqrtPriceX96 in a Uniswap pool defined as sqrt(1/0)*2^96.

Uses reduced precision after tick 443636 in order to accommodate the full range of ticks.

function convert1to0RoundingUp(int256 amount, uint160 sqrtPriceX96) internal pure returns (int256);

Parameters

NameTypeDescription
amountint256The amount of token1 to convert into token0
sqrtPriceX96uint160The square root of the price at which to convert amount of token1 into token0

Returns

NameTypeDescription
<none>int256The converted amount of token1 represented in terms of token0

getCrossBalances
​

Get a single collateral balance and requirement in terms of the lowest-priced token for a given set of (token0/token1) collateral balances and requirements.

function getCrossBalances(LeftRightUnsigned tokenData0, LeftRightUnsigned tokenData1, uint160 sqrtPriceX96)
internal
pure
returns (uint256, uint256);

Parameters

NameTypeDescription
tokenData0LeftRightUnsignedLeftRight encoded word with balance of token0 in the right slot, and required balance in left slot
tokenData1LeftRightUnsignedLeftRight encoded word with balance of token1 in the right slot, and required balance in left slot
sqrtPriceX96uint160The price at which to compute the collateral value and requirements

Returns

NameTypeDescription
<none>uint256The combined collateral balance of tokenData0 and tokenData1 in terms of (token0 if price(token1/token0) < 1 and vice versa)
<none>uint256The combined required collateral threshold of tokenData0 and tokenData1 in terms of (token0 if price(token1/token0) < 1 and vice versa)

getAmountsMoved
​

Compute the notional value (for tokenType = 0 and tokenType = 1) represented by a given leg in an option position.

function getAmountsMoved(TokenId tokenId, uint128 positionSize, uint256 legIndex, bool opening)
internal
pure
returns (LeftRightUnsigned);

Parameters

NameTypeDescription
tokenIdTokenIdThe option position identifier
positionSizeuint128The number of option contracts held in this position (each contract can control multiple tokens)
legIndexuint256The leg index of the option contract, can be {0,1,2,3}
openingboolWhether this position is being opened or closed

Returns

NameTypeDescription
<none>LeftRightUnsignedA LeftRight encoded variable containing the amount0 and the amount1 value controlled by this option position's leg

calculateIOAmounts
​

Compute the amount of funds that are moved to or removed from the Panoptic Pool when tokenId is created.

function calculateIOAmounts(TokenId tokenId, uint128 positionSize, uint256 legIndex, bool opening)
internal
pure
returns (LeftRightSigned longs, LeftRightSigned shorts);

Parameters

NameTypeDescription
tokenIdTokenIdThe option position identifier
positionSizeuint128The number of positions minted
legIndexuint256The leg index minted in this position, can be {0,1,2,3}
openingboolWhether this position is being opened or closed

Returns

NameTypeDescription
longsLeftRightSignedA LeftRight-packed word containing the total amount of long positions
shortsLeftRightSignedA LeftRight-packed word containing the amount of short positions