@zarclays/zswap-trident
Version:
41 lines • 318 kB
JSON
{
"language": "Solidity",
"sources": {
"contracts/abstract/Multicall.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.8.0;\n\n/// @notice Helper utility that enables calling multiple local methods in a single call.\n/// @author Modified from Uniswap (https://github.com/Uniswap/v3-periphery/blob/main/contracts/base/Multicall.sol)\n/// License-Identifier: GPL-2.0-or-later\nabstract contract Multicall {\n function multicall(bytes[] calldata data) public payable returns (bytes[] memory results) {\n results = new bytes[](data.length);\n \n for (uint256 i; i < data.length;) {\n (bool success, bytes memory result) = address(this).delegatecall(data[i]);\n\n if (!success) {\n // Next 5 lines from https://ethereum.stackexchange.com/a/83577\n if (result.length < 68) revert();\n assembly {\n result := add(result, 0x04)\n }\n revert(abi.decode(result, (string)));\n }\n\n results[i] = result;\n\n // cannot realistically overflow on human timescales\n unchecked {\n ++i;\n }\n }\n }\n}\n"
},
"contracts/pool/concentrated/ConcentratedLiquidityPoolManager.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.8.0;\n\nimport \"../../abstract/Multicall.sol\";\nimport \"../../abstract/TridentERC721.sol\";\nimport \"../../interfaces/IMasterDeployer.sol\";\nimport \"../../interfaces/IBentoBoxMinimal.sol\";\nimport \"../../interfaces/ITridentRouter.sol\";\nimport \"../../interfaces/IConcentratedLiquidityPoolManager.sol\";\nimport \"../../interfaces/IConcentratedLiquidityPool.sol\";\nimport \"../../interfaces/IPositionManager.sol\";\nimport \"../../libraries/FullMath.sol\";\nimport \"../../libraries/TickMath.sol\";\nimport \"../../libraries/DyDxMath.sol\";\n\n/// @notice Trident Concentrated Liquidity Pool periphery contract that combines non-fungible position management and staking.\ncontract ConcentratedLiquidityPoolManager is IConcentratedLiquidityPoolManagerStruct, IPositionManager, TridentERC721, Multicall {\n event IncreaseLiquidity(address indexed pool, address indexed owner, uint256 indexed positionId, uint128 liquidity);\n event DecreaseLiquidity(address indexed pool, address indexed owner, uint256 indexed positionId, uint128 liquidity);\n\n address internal cachedMsgSender = address(1);\n address internal cachedPool = address(1);\n\n address internal immutable wETH;\n IBentoBoxMinimal public immutable bento;\n IMasterDeployer public immutable masterDeployer;\n\n mapping(uint256 => Position) public positions;\n\n constructor(address _masterDeployer, address _wETH) {\n masterDeployer = IMasterDeployer(_masterDeployer);\n IBentoBoxMinimal _bento = IBentoBoxMinimal(IMasterDeployer(_masterDeployer).bento());\n _bento.registerProtocol();\n bento = _bento;\n wETH = _wETH;\n mint(address(this));\n }\n\n function mint(\n IConcentratedLiquidityPool pool,\n int24 lowerOld,\n int24 lower,\n int24 upperOld,\n int24 upper,\n uint128 amount0Desired,\n uint128 amount1Desired,\n bool native,\n uint256 minLiquidity,\n uint256 positionId\n ) external payable returns (uint256 _positionId) {\n require(masterDeployer.pools(address(pool)), \"INVALID_POOL\");\n\n cachedMsgSender = msg.sender;\n cachedPool = address(pool);\n\n uint128 liquidityMinted = uint128(\n pool.mint(\n IConcentratedLiquidityPoolStruct.MintParams({\n lowerOld: lowerOld,\n lower: lower,\n upperOld: upperOld,\n upper: upper,\n amount0Desired: amount0Desired,\n amount1Desired: amount1Desired,\n native: native\n })\n )\n );\n\n require(liquidityMinted >= minLiquidity, \"TOO_LITTLE_RECEIVED\");\n\n (uint256 feeGrowthInside0, uint256 feeGrowthInside1) = pool.rangeFeeGrowth(lower, upper);\n\n if (positionId == 0) {\n // We mint a new NFT.\n _positionId = nftCount.minted;\n positions[_positionId] = Position({\n pool: pool,\n liquidity: liquidityMinted,\n lower: lower,\n upper: upper,\n latestAddition: uint32(block.timestamp),\n feeGrowthInside0: feeGrowthInside0,\n feeGrowthInside1: feeGrowthInside1\n });\n mint(msg.sender);\n } else {\n // We increase liquidity for an existing NFT.\n _positionId = positionId;\n Position storage position = positions[_positionId];\n require(address(position.pool) == address(pool), \"POOL_MIS_MATCH\");\n require(position.lower == lower && position.upper == upper, \"RANGE_MIS_MATCH\");\n require(ownerOf(positionId) == msg.sender, \"NOT_ID_OWNER\");\n // Fees should be claimed first.\n position.feeGrowthInside0 = feeGrowthInside0;\n position.feeGrowthInside1 = feeGrowthInside1;\n position.liquidity += liquidityMinted;\n // Incentives should be claimed first.\n position.latestAddition = uint32(block.timestamp);\n }\n\n emit IncreaseLiquidity(address(pool), msg.sender, _positionId, liquidityMinted);\n\n cachedMsgSender = address(1);\n cachedPool = address(1);\n }\n\n function mintCallback(\n address token0,\n address token1,\n uint256 amount0,\n uint256 amount1,\n bool native\n ) external override {\n require(msg.sender == cachedPool, \"UNAUTHORIZED_CALLBACK\");\n if (native) {\n _depositFromUserToBentoBox(token0, cachedMsgSender, msg.sender, amount0);\n _depositFromUserToBentoBox(token1, cachedMsgSender, msg.sender, amount1);\n } else {\n bento.transfer(token0, cachedMsgSender, msg.sender, amount0);\n bento.transfer(token1, cachedMsgSender, msg.sender, amount1);\n }\n cachedMsgSender = address(1);\n cachedPool = address(1);\n }\n\n function burn(\n uint256 tokenId,\n uint128 amount,\n address recipient,\n bool unwrapBento,\n uint256 minimumOut0,\n uint256 minimumOut1\n ) external returns (uint256 token0Amount, uint256 token1Amount) {\n require(msg.sender == ownerOf(tokenId), \"NOT_ID_OWNER\");\n\n Position memory position = positions[tokenId];\n\n (uint256 token0Fees, uint256 token1Fees, uint256 feeGrowthInside0, uint256 feeGrowthInside1) = positionFees(tokenId);\n\n if (amount < position.liquidity) {\n (token0Amount, token1Amount, , ) = position.pool.burn(position.lower, position.upper, amount);\n\n positions[tokenId].feeGrowthInside0 = feeGrowthInside0;\n positions[tokenId].feeGrowthInside1 = feeGrowthInside1;\n positions[tokenId].liquidity -= amount;\n } else {\n amount = position.liquidity;\n (token0Amount, token1Amount, , ) = position.pool.burn(position.lower, position.upper, amount);\n burn(tokenId);\n delete positions[tokenId];\n }\n\n require(token0Amount >= minimumOut0 && token1Amount >= minimumOut1, \"TOO_LITTLE_RECEIVED\");\n\n unchecked {\n token0Amount += token0Fees;\n token1Amount += token1Fees;\n }\n\n _transferBoth(position.pool, recipient, token0Amount, token1Amount, unwrapBento);\n\n emit DecreaseLiquidity(address(position.pool), msg.sender, tokenId, amount);\n }\n\n function collect(\n uint256 tokenId,\n address recipient,\n bool unwrapBento\n ) public returns (uint256 token0amount, uint256 token1amount) {\n require(msg.sender == ownerOf(tokenId), \"NOT_ID_OWNER\");\n Position storage position = positions[tokenId];\n\n (, , , , , , address token0, address token1) = position.pool.getImmutables();\n\n (token0amount, token1amount, position.feeGrowthInside0, position.feeGrowthInside1) = positionFees(tokenId);\n\n uint256 balance0 = bento.balanceOf(token0, address(this));\n uint256 balance1 = bento.balanceOf(token1, address(this));\n\n if (balance0 < token0amount || balance1 < token1amount) {\n (uint256 amount0fees, uint256 amount1fees) = position.pool.collect(position.lower, position.upper);\n\n uint256 newBalance0 = amount0fees + balance0;\n uint256 newBalance1 = amount1fees + balance1;\n\n // Rounding errors due to frequent claiming of other users in the same position may cost us some wei units.\n if (token0amount > newBalance0) token0amount = newBalance0;\n if (token1amount > newBalance1) token1amount = newBalance1;\n }\n\n _transferOut(token0, recipient, token0amount, unwrapBento);\n _transferOut(token1, recipient, token1amount, unwrapBento);\n }\n\n /// @notice Returns the claimable fees and the fee growth accumulators of a given position.\n function positionFees(uint256 tokenId)\n public\n view\n returns (\n uint256 token0amount,\n uint256 token1amount,\n uint256 feeGrowthInside0,\n uint256 feeGrowthInside1\n )\n {\n Position memory position = positions[tokenId];\n\n (feeGrowthInside0, feeGrowthInside1) = position.pool.rangeFeeGrowth(position.lower, position.upper);\n\n token0amount = FullMath.mulDiv(\n feeGrowthInside0 - position.feeGrowthInside0,\n position.liquidity,\n 0x100000000000000000000000000000000\n );\n\n token1amount = FullMath.mulDiv(\n feeGrowthInside1 - position.feeGrowthInside1,\n position.liquidity,\n 0x100000000000000000000000000000000\n );\n }\n\n function _transferBoth(\n IConcentratedLiquidityPool pool,\n address to,\n uint256 token0Amount,\n uint256 token1Amount,\n bool unwrapBento\n ) internal {\n (, , , , , , address token0, address token1) = pool.getImmutables();\n _transferOut(token0, to, token0Amount, unwrapBento);\n _transferOut(token1, to, token1Amount, unwrapBento);\n }\n\n function _transferOut(\n address token,\n address to,\n uint256 shares,\n bool unwrapBento\n ) internal {\n if (unwrapBento) {\n bento.withdraw(token, address(this), to, 0, shares);\n } else {\n bento.transfer(token, address(this), to, shares);\n }\n }\n\n function _depositFromUserToBentoBox(\n address token,\n address sender,\n address recipient,\n uint256 amount\n ) internal {\n if (token == wETH && address(this).balance > 0) {\n // 'amount' is in BentoBox share units.\n uint256 ethAmount = bento.toAmount(token, amount, true);\n if (address(this).balance >= ethAmount) {\n bento.deposit{value: ethAmount}(address(0), sender, recipient, 0, amount);\n return;\n }\n }\n bento.deposit(token, sender, recipient, 0, amount);\n }\n}\n"
},
"contracts/abstract/TridentERC721.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\n\nabstract contract TridentERC721 is ERC721 {\n bytes32 public constant PERMIT_TYPEHASH = keccak256(\"Permit(address spender,uint256 tokenId,uint256 nonce,uint256 deadline)\");\n\n bytes32 public constant PERMIT_ALL_TYPEHASH = keccak256(\"Permit(address owner,address spender,uint256 nonce,uint256 deadline)\");\n\n bytes32 internal immutable _DOMAIN_SEPARATOR;\n\n uint256 internal immutable DOMAIN_SEPARATOR_CHAIN_ID;\n\n struct NFTCounter {\n uint128 minted;\n uint128 burned;\n }\n\n NFTCounter public nftCount;\n\n mapping(uint256 => uint256) public nonces;\n\n mapping(address => uint256) public noncesForAll;\n\n constructor() ERC721(\"TridentNFT\", \"tNFT\") {\n DOMAIN_SEPARATOR_CHAIN_ID = block.chainid;\n _DOMAIN_SEPARATOR = _calculateDomainSeparator();\n }\n\n function _calculateDomainSeparator() internal view returns (bytes32 domainSeperator) {\n domainSeperator = keccak256(\n abi.encode(\n keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n keccak256(bytes(\"TridentNFT\")),\n keccak256(bytes(\"1\")),\n block.chainid,\n address(this)\n )\n );\n }\n\n function DOMAIN_SEPARATOR() public view returns (bytes32 domainSeperator) {\n domainSeperator = block.chainid == DOMAIN_SEPARATOR_CHAIN_ID ? _DOMAIN_SEPARATOR : _calculateDomainSeparator();\n }\n\n function mint(address recipient) internal {\n _mint(recipient, nftCount.minted++);\n }\n\n function burn(uint256 tokenId) internal {\n nftCount.burned++;\n _burn(tokenId);\n }\n\n function totalSupply() public view returns (uint256) {\n return nftCount.minted - nftCount.burned;\n }\n\n function permit(\n address spender,\n uint256 tokenId,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n address owner = ownerOf(tokenId);\n /// @dev This is reasonably safe from overflow - incrementing `nonces` beyond\n // 'type(uint256).max' is exceedingly unlikely compared to optimization benefits.\n unchecked {\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(abi.encode(PERMIT_TYPEHASH, spender, tokenId, nonces[tokenId]++, deadline))\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(recoveredAddress != address(0), \"INVALID_PERMIT_SIGNATURE\");\n require(recoveredAddress == owner || isApprovedForAll(owner, recoveredAddress), \"INVALID_SIGNER\");\n }\n _approve(spender, tokenId);\n }\n\n function permitAll(\n address owner,\n address operator,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external {\n require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n /// @dev This is reasonably safe from overflow - incrementing `nonces` beyond\n // 'type(uint256).max' is exceedingly unlikely compared to optimization benefits.\n unchecked {\n bytes32 digest = keccak256(\n abi.encodePacked(\n \"\\x19\\x01\",\n DOMAIN_SEPARATOR(),\n keccak256(abi.encode(PERMIT_ALL_TYPEHASH, owner, operator, noncesForAll[owner]++, deadline))\n )\n );\n address recoveredAddress = ecrecover(digest, v, r, s);\n require(\n (recoveredAddress != address(0) && recoveredAddress == owner) || isApprovedForAll(owner, recoveredAddress),\n \"INVALID_PERMIT_SIGNATURE\"\n );\n }\n _setApprovalForAll(owner, operator, true);\n }\n}\n"
},
"contracts/interfaces/IMasterDeployer.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.8.0;\n\n/// @notice Trident pool deployer interface.\ninterface IMasterDeployer {\n function barFee() external view returns (uint256);\n\n function barFeeTo() external view returns (address);\n\n function bento() external view returns (address);\n\n function migrator() external view returns (address);\n\n function pools(address pool) external view returns (bool);\n\n function deployPool(address factory, bytes calldata deployData) external returns (address);\n}\n"
},
"contracts/interfaces/IBentoBoxMinimal.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.8.0;\n\nimport \"../libraries/RebaseLibrary.sol\";\n\n/// @notice Minimal BentoBox vault interface.\n/// @dev `token` is aliased as `address` from `IERC20` for simplicity.\ninterface IBentoBoxMinimal {\n /// @notice Balance per ERC-20 token per account in shares.\n function balanceOf(address, address) external view returns (uint256);\n\n /// @dev Helper function to represent an `amount` of `token` in shares.\n /// @param token The ERC-20 token.\n /// @param amount The `token` amount.\n /// @param roundUp If the result `share` should be rounded up.\n /// @return share The token amount represented in shares.\n function toShare(\n address token,\n uint256 amount,\n bool roundUp\n ) external view returns (uint256 share);\n\n /// @dev Helper function to represent shares back into the `token` amount.\n /// @param token The ERC-20 token.\n /// @param share The amount of shares.\n /// @param roundUp If the result should be rounded up.\n /// @return amount The share amount back into native representation.\n function toAmount(\n address token,\n uint256 share,\n bool roundUp\n ) external view returns (uint256 amount);\n\n /// @notice Registers this contract so that users can approve it for BentoBox.\n function registerProtocol() external;\n\n /// @notice Deposit an amount of `token` represented in either `amount` or `share`.\n /// @param token The ERC-20 token to deposit.\n /// @param from which account to pull the tokens.\n /// @param to which account to push the tokens.\n /// @param amount Token amount in native representation to deposit.\n /// @param share Token amount represented in shares to deposit. Takes precedence over `amount`.\n /// @return amountOut The amount deposited.\n /// @return shareOut The deposited amount represented in shares.\n function deposit(\n address token,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external payable returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Withdraws an amount of `token` from a user account.\n /// @param token_ The ERC-20 token to withdraw.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param amount of tokens. Either one of `amount` or `share` needs to be supplied.\n /// @param share Like above, but `share` takes precedence over `amount`.\n function withdraw(\n address token_,\n address from,\n address to,\n uint256 amount,\n uint256 share\n ) external returns (uint256 amountOut, uint256 shareOut);\n\n /// @notice Transfer shares from a user account to another one.\n /// @param token The ERC-20 token to transfer.\n /// @param from which user to pull the tokens.\n /// @param to which user to push the tokens.\n /// @param share The amount of `token` in shares.\n function transfer(\n address token,\n address from,\n address to,\n uint256 share\n ) external;\n\n /// @dev Reads the Rebase `totals`from storage for a given token\n function totals(address token) external view returns (Rebase memory total);\n\n /// @dev Approves users' BentoBox assets to a \"master\" contract.\n function setMasterContractApproval(\n address user,\n address masterContract,\n bool approved,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n function harvest(\n address token,\n bool balance,\n uint256 maxChangeAmount\n ) external;\n}\n"
},
"contracts/interfaces/ITridentRouter.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.8.0;\n\n/// @notice Trident pool router interface.\ninterface ITridentRouter {\n struct Path {\n address pool;\n bytes data;\n }\n\n struct ExactInputSingleParams {\n uint256 amountIn;\n uint256 amountOutMinimum;\n address pool;\n address tokenIn;\n bytes data;\n }\n\n struct ExactInputParams {\n address tokenIn;\n uint256 amountIn;\n uint256 amountOutMinimum;\n Path[] path;\n }\n\n struct TokenInput {\n address token;\n bool native;\n uint256 amount;\n }\n\n struct InitialPath {\n address tokenIn;\n address pool;\n bool native;\n uint256 amount;\n bytes data;\n }\n\n struct PercentagePath {\n address tokenIn;\n address pool;\n uint64 balancePercentage; // Multiplied by 10^6. 100% = 100_000_000\n bytes data;\n }\n\n struct Output {\n address token;\n address to;\n bool unwrapBento;\n uint256 minAmount;\n }\n\n struct ComplexPathParams {\n InitialPath[] initialPath;\n PercentagePath[] percentagePath;\n Output[] output;\n }\n}\n"
},
"contracts/interfaces/IConcentratedLiquidityPoolManager.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.8.0;\n\nimport \"./IConcentratedLiquidityPool.sol\";\nimport \"./ITridentNFT.sol\";\n\n/// @notice Trident concentrated liquidity pool manager contract Structs.\ninterface IConcentratedLiquidityPoolManagerStruct {\n struct Position {\n IConcentratedLiquidityPool pool;\n uint128 liquidity;\n int24 lower;\n int24 upper;\n uint32 latestAddition;\n uint256 feeGrowthInside0; /// @dev Per unit of liquidity.\n uint256 feeGrowthInside1;\n }\n}\n\n/// @notice Trident concentrated liquidity manager contract interface.\ninterface IConcentratedLiquidityPoolManager is IConcentratedLiquidityPoolManagerStruct, ITridentNFT {\n function positions(uint256) external view returns (Position memory);\n\n function bento() external view returns (IBentoBoxMinimal);\n}\n"
},
"contracts/interfaces/IConcentratedLiquidityPool.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.8.0;\n\nimport \"./IBentoBoxMinimal.sol\";\nimport \"./IMasterDeployer.sol\";\nimport \"../libraries/Ticks.sol\";\n\n/// @notice Trident concentrated liquidity pool contract Structs.\ninterface IConcentratedLiquidityPoolStruct {\n struct Tick {\n int24 previousTick;\n int24 nextTick;\n uint128 liquidity;\n uint256 feeGrowthOutside0; // Per unit of liquidity.\n uint256 feeGrowthOutside1;\n uint160 secondsGrowthOutside;\n }\n struct Position {\n uint128 liquidity;\n uint256 feeGrowthInside0Last;\n uint256 feeGrowthInside1Last;\n }\n\n struct MintParams {\n int24 lowerOld;\n int24 lower;\n int24 upperOld;\n int24 upper;\n uint128 amount0Desired;\n uint128 amount1Desired;\n bool native;\n }\n\n struct SwapCache {\n uint256 feeAmount;\n uint256 totalFeeAmount;\n uint256 protocolFee;\n uint256 feeGrowthGlobalA;\n uint256 feeGrowthGlobalB;\n uint256 currentPrice;\n uint256 currentLiquidity;\n uint256 input;\n int24 nextTickToCross;\n }\n}\n\n/// @notice Trident Concentrated Liquidity Pool interface.\ninterface IConcentratedLiquidityPool is IConcentratedLiquidityPoolStruct {\n function ticks(int24 _tick) external view returns (Tick memory);\n\n function positions(\n address owner,\n int24 lower,\n int24 upper\n ) external view returns (Position memory);\n\n function feeGrowthGlobal0() external view returns (uint256);\n\n function feeGrowthGlobal1() external view returns (uint256);\n\n function rangeFeeGrowth(int24 lowerTick, int24 upperTick) external view returns (uint256 feeGrowthInside0, uint256 feeGrowthInside1);\n\n function setPrice(uint160 price) external;\n\n function collect(int24 lower, int24 upper) external returns (uint256 amount0fees, uint256 amount1fees);\n\n function mint(MintParams memory data) external returns (uint256 liquidityMinted);\n\n function burn(\n int24 lower,\n int24 upper,\n uint128 amount\n )\n external\n returns (\n uint256 token0Amount,\n uint256 token1Amount,\n uint256 token0Fees,\n uint256 token1Fees\n );\n\n function getImmutables()\n external\n view\n returns (\n uint128 _MAX_TICK_LIQUIDITY,\n uint24 _tickSpacing,\n uint24 _swapFee,\n address _barFeeTo,\n IBentoBoxMinimal _bento,\n IMasterDeployer _masterDeployer,\n address _token0,\n address _token1\n );\n\n function getPriceAndNearestTicks() external view returns (uint160 _price, int24 _nearestTick);\n\n function getTokenProtocolFees() external view returns (uint128 _token0ProtocolFee, uint128 _token1ProtocolFee);\n\n function getReserves() external view returns (uint128 _reserve0, uint128 _reserve1);\n\n function getAssets() external view returns (address[] memory tokens);\n\n function getSecondsGrowthAndLastObservation() external view returns (uint160 _secondGrowthGlobal, uint32 _lastObservation);\n}\n"
},
"contracts/interfaces/IPositionManager.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.8.0;\n\n/// @notice Trident concentrated Liquidity pool mint callback receiver.\ninterface IPositionManager {\n function mintCallback(\n address token0,\n address token1,\n uint256 amount0,\n uint256 amount1,\n bool native\n ) external;\n}\n"
},
"contracts/libraries/FullMath.sol": {
"content": "// SPDX-License-Identifier: MIT\n\npragma solidity >=0.8.0;\n\n/// @notice Math library that facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision.\n/// @author Adapted from https://github.com/Uniswap/uniswap-v3-core/blob/main/contracts/libraries/FullMath.sol.\n/// @dev Handles \"phantom overflow\", i.e., allows multiplication and division where an intermediate value overflows 256 bits.\nlibrary FullMath {\n /// @notice Calculates floor(a×b÷denominator) with full precision - throws if result overflows an uint256 or denominator == 0.\n /// @param a The multiplicand.\n /// @param b The multiplier.\n /// @param denominator The divisor.\n /// @return result The 256-bit result.\n /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv.\n function mulDiv(\n uint256 a,\n uint256 b,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = a * b.\n // Compute the product mod 2**256 and mod 2**256 - 1,\n // then use the Chinese Remainder Theorem to reconstruct\n // the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2**256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product.\n uint256 prod1; // Most significant 256 bits of the product.\n assembly {\n let mm := mulmod(a, b, not(0))\n prod0 := mul(a, b)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n require(denominator > 0);\n assembly {\n result := div(prod0, denominator)\n }\n return result;\n }\n // Make sure the result is less than 2**256 -\n // also prevents denominator == 0.\n require(denominator > prod1);\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n // Make division exact by subtracting the remainder from [prod1 prod0] -\n // compute remainder using mulmod.\n uint256 remainder;\n assembly {\n remainder := mulmod(a, b, denominator)\n }\n // Subtract 256 bit number from 512 bit number.\n assembly {\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n // Factor powers of two out of denominator -\n // compute largest power of two divisor of denominator\n // (always >= 1).\n uint256 twos = uint256(-int256(denominator)) & denominator;\n // Divide denominator by power of two.\n assembly {\n denominator := div(denominator, twos)\n }\n // Divide [prod1 prod0] by the factors of two.\n assembly {\n prod0 := div(prod0, twos)\n }\n // Shift in bits from prod1 into prod0. For this we need\n // to flip `twos` such that it is 2**256 / twos -\n // if twos is zero, then it becomes one.\n assembly {\n twos := add(div(sub(0, twos), twos), 1)\n }\n prod0 |= prod1 * twos;\n // Invert denominator mod 2**256 -\n // now that denominator is an odd number, it has an inverse\n // modulo 2**256 such that denominator * inv = 1 mod 2**256.\n // Compute the inverse by starting with a seed that is correct\n // for four bits. That is, denominator * inv = 1 mod 2**4.\n uint256 inv = (3 * denominator) ^ 2;\n // Now use Newton-Raphson iteration to improve the precision.\n // Thanks to Hensel's lifting lemma, this also works in modular\n // arithmetic, doubling the correct bits in each step.\n inv *= 2 - denominator * inv; // Inverse mod 2**8.\n inv *= 2 - denominator * inv; // Inverse mod 2**16.\n inv *= 2 - denominator * inv; // Inverse mod 2**32.\n inv *= 2 - denominator * inv; // Inverse mod 2**64.\n inv *= 2 - denominator * inv; // Inverse mod 2**128.\n inv *= 2 - denominator * inv; // Inverse mod 2**256.\n // Because the division is now exact we can divide by multiplying\n // with the modular inverse of denominator. This will give us the\n // correct result modulo 2**256. Since the precoditions guarantee\n // that the outcome is less than 2**256, this is the final result.\n // We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inv;\n return result;\n }\n }\n\n /// @notice Calculates ceil(a×b÷denominator) with full precision - throws if result overflows an uint256 or denominator == 0.\n /// @param a The multiplicand.\n /// @param b The multiplier.\n /// @param denominator The divisor.\n /// @return result The 256-bit result.\n function mulDivRoundingUp(\n uint256 a,\n uint256 b,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n result = mulDiv(a, b, denominator);\n unchecked {\n if (mulmod(a, b, denominator) != 0) {\n require(result < type(uint256).max);\n result++;\n }\n }\n }\n}\n"
},
"contracts/libraries/TickMath.sol": {
"content": "// SPDX-License-Identifier: GPL-2.0-or-later\n\npragma solidity >=0.8.0;\n\n/// @notice Math library for computing sqrt price for ticks of size 1.0001, i.e., sqrt(1.0001^tick) as fixed point Q64.96 numbers - supports\n/// prices between 2**-128 and 2**128 - 1.\n/// @author Adapted from https://github.com/Uniswap/uniswap-v3-core/blob/main/contracts/libraries/TickMath.sol.\nlibrary TickMath {\n /// @dev The minimum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**-128.\n int24 internal constant MIN_TICK = -887272;\n /// @dev The maximum tick that may be passed to #getSqrtRatioAtTick computed from log base 1.0001 of 2**128 - 1.\n int24 internal constant MAX_TICK = -MIN_TICK;\n /// @dev The minimum value that can be returned from #getSqrtRatioAtTick - equivalent to getSqrtRatioAtTick(MIN_TICK).\n uint160 internal constant MIN_SQRT_RATIO = 4295128739;\n /// @dev The maximum value that can be returned from #getSqrtRatioAtTick - equivalent to getSqrtRatioAtTick(MAX_TICK).\n uint160 internal constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;\n\n error TickOutOfBounds();\n error PriceOutOfBounds();\n\n /// @notice Calculates sqrt(1.0001^tick) * 2^96.\n /// @dev Throws if |tick| > max tick.\n /// @param tick The input tick for the above formula.\n /// @return sqrtPriceX96 Fixed point Q64.96 number representing the sqrt of the ratio of the two assets (token1/token0)\n /// at the given tick.\n function getSqrtRatioAtTick(int24 tick) internal pure returns (uint160 sqrtPriceX96) {\n uint256 absTick = tick < 0 ? uint256(-int256(tick)) : uint256(int256(tick));\n if (absTick > uint256(uint24(MAX_TICK))) revert TickOutOfBounds();\n unchecked {\n uint256 ratio = absTick & 0x1 != 0 ? 0xfffcb933bd6fad37aa2d162d1a594001 : 0x100000000000000000000000000000000;\n if (absTick & 0x2 != 0) ratio = (ratio * 0xfff97272373d413259a46990580e213a) >> 128;\n if (absTick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656932ef12357cf3c7fdcc) >> 128;\n if (absTick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e4e61c3624eaa0941cd0) >> 128;\n if (absTick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f6159c9db58835c926644) >> 128;\n if (absTick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98c081472e6896dfb254c0) >> 128;\n if (absTick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c96a3843ec78b326b52861) >> 128;\n if (absTick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99a2a811c461f1969c3053) >> 128;\n if (absTick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900a88aedcffc83b479aa3a4) >> 128;\n if (absTick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac413176f2b074cf7815e54) >> 128;\n if (absTick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b70005940c7a398e4b70f3) >> 128;\n if (absTick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c29b7443b29c7fa6e889d9) >> 128;\n if (absTick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd2022b8845ad8f792aa5825) >> 128;\n if (absTick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d870fdf8a65dc1f90e061e5) >> 128;\n if (absTick & 0x4000 != 0) ratio = (ratio * 0x70d869a156d2a1b890bb3df62baf32f7) >> 128;\n if (absTick & 0x8000 != 0) ratio = (ratio * 0x31be135f97d08fd981231505542fcfa6) >> 128;\n if (absTick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7a84e1c677de54f3e99bc9) >> 128;\n if (absTick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedb81196699c329225ee604) >> 128;\n if (absTick & 0x40000 != 0) ratio = (ratio * 0x2216e584f5fa1ea926041bedfe98) >> 128;\n if (absTick & 0x80000 != 0) ratio = (ratio * 0x48a170391f7dc42444e8fa2) >> 128;\n\n if (tick > 0) ratio = type(uint256).max / ratio;\n // This divides by 1<<32 rounding up to go from a Q128.128 to a Q128.96.\n // We then downcast because we know the result always fits within 160 bits due to our tick input constraint.\n // We round up in the division so getTickAtSqrtRatio of the output price is always consistent.\n sqrtPriceX96 = uint160((ratio >> 32) + (ratio % (1 << 32) == 0 ? 0 : 1));\n }\n }\n\n function validatePrice(uint160 price) internal pure {\n if (price < MIN_SQRT_RATIO || price >= MAX_SQRT_RATIO) revert PriceOutOfBounds();\n }\n\n /// @notice Calculates the greatest tick value such that getRatioAtTick(tick) <= ratio.\n /// @dev Throws in case sqrtPriceX96 < MIN_SQRT_RATIO, as MIN_SQRT_RATIO is the lowest value getRatioAtTick may\n /// ever return.\n /// @param sqrtPriceX96 The sqrt ratio for which to compute the tick as a Q64.96.\n /// @return tick The greatest tick for which the ratio is less than or equal to the input ratio.\n function getTickAtSqrtRatio(uint160 sqrtPriceX96) internal pure returns (int24 tick) {\n // Second inequality must be < because the price can never reach the price at the max tick.\n if (sqrtPriceX96 < MIN_SQRT_RATIO || sqrtPriceX96 >= MAX_SQRT_RATIO) revert PriceOutOfBounds();\n uint256 ratio = uint256(sqrtPriceX96) << 32;\n\n uint256 r = ratio;\n uint256 msb;\n\n assembly {\n let f := shl(7, gt(r, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(6, gt(r, 0xFFFFFFFFFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(5, gt(r, 0xFFFFFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(4, gt(r, 0xFFFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(3, gt(r, 0xFF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(2, gt(r, 0xF))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := shl(1, gt(r, 0x3))\n msb := or(msb, f)\n r := shr(f, r)\n }\n assembly {\n let f := gt(r, 0x1)\n msb := or(msb, f)\n }\n unchecked {\n if (msb >= 128) r = ratio >> (msb - 127);\n else r = ratio << (127 - msb);\n\n int256 log_2 = (int256(msb) - 128) << 64;\n\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(63, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(62, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(61, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(60, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(59, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(58, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(57, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(56, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(55, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(54, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(53, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(52, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(51, f))\n r := shr(f, r)\n }\n assembly {\n r := shr(127, mul(r, r))\n let f := shr(128, r)\n log_2 := or(log_2, shl(50, f))\n }\n\n int256 log_sqrt10001 = log_2 * 255738958999603826347141; // 128.128 number.\n\n int24 tickLow = int24((log_sqrt10001 - 3402992956809132418596140100660247210) >> 128);\n int24 tickHi = int24((log_sqrt10001 + 291339464771989622907027621153398088495) >> 128);\n\n tick = tickLow == tickHi ? tickLow : getSqrtRatioAtTick(tickHi) <= sqrtPriceX96 ? tickHi : tickLow;\n }\n }\n}\n"
},
"contracts/libraries/DyDxMath.sol": {
"content": "// SPDX-License-Identifier: GPL-3.0-or-later\n\npragma solidity >=0.8.0;\n\nimport \"./FullMath.sol\";\nimport \"./UnsafeMath.sol\";\nimport \"./SafeCast.sol\";\n\n/// @notice Math library that facilitates ranged liquidity calculations.\nlibrary DyDxMath {\n function getDy(\n uint256 liquidity,\n uint256 priceLower,\n uint256 priceUpper,\n bool roundUp\n ) internal pure returns (uint256 dy) {\n unchecked {\n if (roundUp) {\n dy = FullMath.mulDivRoundingUp(liquidity, priceUpper - priceLower, 0x1000000000000000000000000);\n } else {\n dy = FullMath.mulDiv(liquidity, priceUpper - priceLower, 0x1000000000000000000000000);\n }\n }\n }\n\n function getDx(\n uint256 liquidity,\n uint256 priceLower,\n uint256 priceUpper,\n bool roundUp\n ) internal pure returns (uint256 dx) {\n unchecked {\n if (roundUp) {\n dx = UnsafeMath.divRoundingUp(FullMath.mulDivRoundingUp(liquidity << 96, priceUpper - priceLower, priceUpper), priceLower);\n } else {\n dx = FullMath.mulDiv(liquidity << 96, priceUpper - priceLower, priceUpper) / priceLower;\n }\n }\n }\n\n function getLiquidityForAmounts(\n uint256 priceLower,\n uint256 priceUpper,\n uint256 currentPrice,\n uint256 dy,\n uint256 dx\n ) public pure returns (uint256 liquidity) {\n unchecked {\n if (priceUpper <= currentPrice) {\n liquidity = FullMath.mulDiv(dy, 0x1000000000000000000000000, priceUpper - priceLower);\n } else if (currentPrice <= priceLower) {\n liquidity = FullMath.mulDiv(\n dx,\n FullMath.mulDiv(priceLower, priceUpper, 0x1000000000000000000000000),\n priceUpper - priceLower\n );\n } else {\n uint256 liquidity0 = FullMath.mulDiv(\n dx,\n FullMath.mulDiv(priceUpper, currentPrice, 0x1000000000000000000000000),\n priceUpper - currentPrice\n );\n uint256 liquidity1 = FullMath.mulDiv(dy, 0x1000000000000000000000000, currentPrice - priceLower);\n liquidity = liquidity0 < liquidity1 ? liquidity0 : liquidity1;\n }\n }\n }\n\n function getAmountsForLiquidity(\n uint256 priceLower,\n uint256 priceUpper,\n uint256 currentPrice,\n uint256 liquidityAmount,\n bool roundUp\n ) internal pure returns (uint128 token0amount, uint128 token1amount) {\n if (priceUpper <= currentPrice) {\n // Only supply `token1` (`token1` is Y).\n token1amount = SafeCast.toUint128(DyDxMath.getDy(liquidityAmount, priceLower, priceUpper, roundUp));\n } else if (currentPrice <= priceLower) {\n // Only supply `token0` (`token0` is X).\n token0amount = SafeCast.toUint128(DyDxMath.getDx(liquidityAmount, priceLower, priceUpper, roundUp));\n } else {\n // Supply both tokens.\n token0amount = SafeCast.toUint128(DyDxMath.getDx(liquidityAmount, currentPrice, priceUpper, roundUp));\n token1amount = SafeCast.toUint128(DyDxMath.getDy(liquidityAmount, priceLower, currentPrice, roundUp));\n }\n }\n}\n"
},
"@openzeppelin/contracts/token/ERC721/ERC721.sol": {
"content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: address zero is not a valid owner\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _owners[tokenId];\n require(owner != address(0), \"ERC721: invalid token ID\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n _requireMinted(tokenId);\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not token owner nor approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n _requireMinted(tokenId);\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n func