Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 1,257 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Input Single Wit... | 21234550 | 2 days ago | IN | 0 ETH | 0.00138986 | ||||
Input Single Wit... | 21223992 | 3 days ago | IN | 0.01 ETH | 0.002412 | ||||
Input Single Wit... | 21209588 | 5 days ago | IN | 0 ETH | 0.00107565 | ||||
Input Single Wit... | 21198656 | 7 days ago | IN | 0.01 ETH | 0.00160501 | ||||
Input Single Wit... | 21197266 | 7 days ago | IN | 0 ETH | 0.0015421 | ||||
Input Single Wit... | 21181521 | 9 days ago | IN | 0.002 ETH | 0.00777311 | ||||
Input Single Wit... | 21178291 | 10 days ago | IN | 0 ETH | 0.00301922 | ||||
Input Single Wit... | 21176393 | 10 days ago | IN | 0 ETH | 0.00240772 | ||||
Input Single Wit... | 21174567 | 10 days ago | IN | 0.01 ETH | 0.00443551 | ||||
Input Single Wit... | 21174566 | 10 days ago | IN | 0.01299999 ETH | 0.00454545 | ||||
Input Single Wit... | 21174565 | 10 days ago | IN | 0.012 ETH | 0.00360564 | ||||
Input Single Wit... | 21174563 | 10 days ago | IN | 0.01099999 ETH | 0.004292 | ||||
Input Single Wit... | 21174563 | 10 days ago | IN | 0.012 ETH | 0.0043954 | ||||
Input Single Wit... | 21174560 | 10 days ago | IN | 0.012 ETH | 0.00435108 | ||||
Input Single Wit... | 21174560 | 10 days ago | IN | 0.01099999 ETH | 0.00445749 | ||||
Input Single Wit... | 21167927 | 11 days ago | IN | 0 ETH | 0.00389614 | ||||
Input Single Wit... | 21167816 | 11 days ago | IN | 0 ETH | 0.00403848 | ||||
Input Single Wit... | 21167625 | 11 days ago | IN | 0 ETH | 0.00383182 | ||||
Input Single Wit... | 21154898 | 13 days ago | IN | 0 ETH | 0.00122538 | ||||
Input Single Wit... | 21154893 | 13 days ago | IN | 0.00016776 ETH | 0.00124526 | ||||
Input Single Wit... | 21153812 | 13 days ago | IN | 0 ETH | 0.00155794 | ||||
Input Single Wit... | 21132483 | 16 days ago | IN | 0 ETH | 0.00257699 | ||||
Input Single Wit... | 21128080 | 17 days ago | IN | 0 ETH | 0.00176043 | ||||
Input Single Wit... | 21127955 | 17 days ago | IN | 0.001 ETH | 0.00160543 | ||||
Input Single Wit... | 21126365 | 17 days ago | IN | 0.049 ETH | 0.00301989 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
21223992 | 3 days ago | 0.01 ETH | ||||
21198656 | 7 days ago | 0.01 ETH | ||||
21181521 | 9 days ago | 0.002 ETH | ||||
21174567 | 10 days ago | 0.01 ETH | ||||
21174566 | 10 days ago | 0.01299999 ETH | ||||
21174565 | 10 days ago | 0.012 ETH | ||||
21174563 | 10 days ago | 0.01099999 ETH | ||||
21174563 | 10 days ago | 0.012 ETH | ||||
21174560 | 10 days ago | 0.012 ETH | ||||
21174560 | 10 days ago | 0.01099999 ETH | ||||
21154893 | 13 days ago | 0.00016776 ETH | ||||
21127955 | 17 days ago | 0.001 ETH | ||||
21126365 | 17 days ago | 0.049 ETH | ||||
21124098 | 17 days ago | 0.0577 ETH | ||||
21101279 | 20 days ago | 0.29999999 ETH | ||||
21097019 | 21 days ago | 0.001 ETH | ||||
21078512 | 24 days ago | 0.00001 ETH | ||||
21032858 | 30 days ago | 0.02 ETH | ||||
21019455 | 32 days ago | 0.0001 ETH | ||||
21014572 | 33 days ago | 0.0003 ETH | ||||
21014561 | 33 days ago | 0.0007 ETH | ||||
20985743 | 37 days ago | 0.0001 ETH | ||||
20976618 | 38 days ago | 0.02 ETH | ||||
20971443 | 39 days ago | 0.000013 ETH | ||||
20969086 | 39 days ago | 0.001 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
MaverickV2Router
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 5500 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IMaverickV2Factory} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Factory.sol"; import {IMaverickV2Router} from "./interfaces/IMaverickV2Router.sol"; import {CallbackOperations} from "./routerbase/CallbackOperations.sol"; import {PushOperations} from "./routerbase/PushOperations.sol"; import {Checks} from "./base/Checks.sol"; import {State} from "./paymentbase/State.sol"; import {IWETH9} from "./paymentbase/IWETH9.sol"; /** * @notice Swap router functions for Maverick V2. This contract requires that * users approve a spending allowance in order to pay for swaps. * * @notice The functions in this contract are partitioned into two subcontracts that * implement both push-based and callback-based swaps. Maverick V2 provides * two mechanisms for paying for a swap: * - Push the input assets to the pool and then call swap. This avoids a * callback to transfer the input assets and is generally more gas efficient but * is only suitable for exact-input swaps where the caller knows how much input * they need to send to the pool. * - Callback payment where the pool calls a callback function on this router * to settle up for the input amount of the swap. */ contract MaverickV2Router is Checks, PushOperations, CallbackOperations, IMaverickV2Router { constructor(IMaverickV2Factory _factory, IWETH9 _weth) State(_factory, _weth) {} }
// SPDX-License-Identifier: GPL-2.0-or-later // As the copyright holder of this work, Ubiquity Labs retains // the right to distribute, use, and modify this code under any license of // their choosing, in addition to the terms of the GPL-v2 or later. pragma solidity ^0.8.25; interface IPayableMulticall { function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); }
// SPDX-License-Identifier: GPL-2.0-or-later // As the copyright holder of this work, Ubiquity Labs retains // the right to distribute, use, and modify this code under any license of // their choosing, in addition to the terms of the GPL-v2 or later. pragma solidity ^0.8.25; import {IPayableMulticall} from "./IPayableMulticall.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; // Modified from https://github.com/OpenZeppelin/openzeppelin-contracts/blob/6ba452dea4258afe77726293435f10baf2bed265/contracts/utils/Multicall.sol /* * @notice Payable multicall; requires all functions in the multicall to also be * payable. */ abstract contract PayableMulticall is IPayableMulticall { /** * @dev This function allows multiple calls to different contract functions * in a single transaction. * @param data An array of encoded function call data. * @return results An array of the results of the function calls. */ function multicall(bytes[] calldata data) external payable returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { results[i] = Address.functionDelegateCall(address(this), data[i]); } } }
// SPDX-License-Identifier: GPL-2.0-or-later // As the copyright holder of this work, Ubiquity Labs retains // the right to distribute, use, and modify this code under any license of // their choosing, in addition to the terms of the GPL-v2 or later. pragma solidity ^0.8.25; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IMaverickV2Pool} from "./IMaverickV2Pool.sol"; interface IMaverickV2Factory { error FactoryInvalidProtocolFeeRatio(uint8 protocolFeeRatioD3); error FactoryInvalidLendingFeeRate(uint256 protocolLendingFeeRateD18); error FactoryProtocolFeeOnRenounce(uint8 protocolFeeRatioD3); error FactorAlreadyInitialized(); error FactorNotInitialized(); error FactoryInvalidTokenOrder(IERC20 _tokenA, IERC20 _tokenB); error FactoryInvalidFee(); error FactoryInvalidKinds(uint8 kinds); error FactoryInvalidTickSpacing(uint256 tickSpacing); error FactoryInvalidLookback(uint256 lookback); error FactoryInvalidTokenDecimals(uint8 decimalsA, uint8 decimalsB); error FactoryPoolAlreadyExists( uint256 feeAIn, uint256 feeBIn, uint256 tickSpacing, uint256 lookback, IERC20 tokenA, IERC20 tokenB, uint8 kinds, address accessor ); error FactoryAccessorMustBeNonZero(); event PoolCreated( IMaverickV2Pool poolAddress, uint8 protocolFeeRatio, uint256 feeAIn, uint256 feeBIn, uint256 tickSpacing, uint256 lookback, int32 activeTick, IERC20 tokenA, IERC20 tokenB, uint8 kinds, address accessor ); event SetFactoryProtocolFeeRatio(uint8 protocolFeeRatioD3); event SetFactoryProtocolLendingFeeRate(uint256 lendingFeeRateD18); event SetFactoryProtocolFeeReceiver(address receiver); struct DeployParameters { uint64 feeAIn; uint64 feeBIn; uint32 lookback; int32 activeTick; uint64 tokenAScale; uint64 tokenBScale; // slot IERC20 tokenA; // slot IERC20 tokenB; // slot uint16 tickSpacing; uint8 options; address accessor; } /** * @notice Called by deployer library to initialize a pool. */ function deployParameters() external view returns ( uint64 feeAIn, uint64 feeBIn, uint32 lookback, int32 activeTick, uint64 tokenAScale, uint64 tokenBScale, // slot IERC20 tokenA, // slot IERC20 tokenB, // slot uint16 tickSpacing, uint8 options, address accessor ); /** * @notice Create a new MaverickV2Pool with symmetric swap fees. * @param fee Fraction of the pool swap amount that is retained as an LP in * D18 scale. * @param tickSpacing Tick spacing of pool where 1.0001^tickSpacing is the * bin width. * @param lookback Pool lookback in seconds. * @param tokenA Address of tokenA. * @param tokenB Address of tokenB. * @param activeTick Tick position that contains the active bins. * @param kinds 1-15 number to represent the active kinds * 0b0001 = static; * 0b0010 = right; * 0b0100 = left; * 0b1000 = both. * E.g. a pool with all 4 modes will have kinds = b1111 = 15 */ function create( uint64 fee, uint16 tickSpacing, uint32 lookback, IERC20 tokenA, IERC20 tokenB, int32 activeTick, uint8 kinds ) external returns (IMaverickV2Pool); /** * @notice Create a new MaverickV2Pool. * @param feeAIn Fraction of the pool swap amount for tokenA-input swaps * that is retained as an LP in D18 scale. * @param feeBIn Fraction of the pool swap amount for tokenB-input swaps * that is retained as an LP in D18 scale. * @param tickSpacing Tick spacing of pool where 1.0001^tickSpacing is the * bin width. * @param lookback Pool lookback in seconds. * @param tokenA Address of tokenA. * @param tokenB Address of tokenB. * @param activeTick Tick position that contains the active bins. * @param kinds 1-15 number to represent the active kinds * 0b0001 = static; * 0b0010 = right; * 0b0100 = left; * 0b1000 = both. * e.g. a pool with all 4 modes will have kinds = b1111 = 15 */ function create( uint64 feeAIn, uint64 feeBIn, uint16 tickSpacing, uint32 lookback, IERC20 tokenA, IERC20 tokenB, int32 activeTick, uint8 kinds ) external returns (IMaverickV2Pool); /** * @notice Create a new MaverickV2PoolPermissioned with symmetric swap fees * with all functions permissioned. Set fee to zero to make the pool fee settable by the accessor. * @param fee Fraction of the pool swap amount that is retained as an LP in * D18 scale. * @param tickSpacing Tick spacing of pool where 1.0001^tickSpacing is the * bin width. * @param lookback Pool lookback in seconds. * @param tokenA Address of tokenA. * @param tokenB Address of tokenB. * @param activeTick Tick position that contains the active bins. * @param kinds 1-15 number to represent the active kinds * 0b0001 = static; * 0b0010 = right; * 0b0100 = left; * 0b1000 = both. * E.g. a pool with all 4 modes will have kinds = b1111 = 15 * @param accessor Only address that can access the pool's public write functions. */ function createPermissioned( uint64 fee, uint16 tickSpacing, uint32 lookback, IERC20 tokenA, IERC20 tokenB, int32 activeTick, uint8 kinds, address accessor ) external returns (IMaverickV2Pool); /** * @notice Create a new MaverickV2PoolPermissioned with all functions * permissioned. Set fees to zero to make the pool fee settable by the * accessor. * @param feeAIn Fraction of the pool swap amount for tokenA-input swaps * that is retained as an LP in D18 scale. * @param feeBIn Fraction of the pool swap amount for tokenB-input swaps * that is retained as an LP in D18 scale. * @param tickSpacing Tick spacing of pool where 1.0001^tickSpacing is the * bin width. * @param lookback Pool lookback in seconds. * @param tokenA Address of tokenA. * @param tokenB Address of tokenB. * @param activeTick Tick position that contains the active bins. * @param kinds 1-15 number to represent the active kinds * 0b0001 = static; * 0b0010 = right; * 0b0100 = left; * 0b1000 = both. * E.g. a pool with all 4 modes will have kinds = b1111 = 15 * @param accessor only address that can access the pool's public write functions. */ function createPermissioned( uint64 feeAIn, uint64 feeBIn, uint16 tickSpacing, uint32 lookback, IERC20 tokenA, IERC20 tokenB, int32 activeTick, uint8 kinds, address accessor ) external returns (IMaverickV2Pool); /** * @notice Create a new MaverickV2PoolPermissioned with the option to make * a subset of function permissionless. Set fee to zero to make the pool * fee settable by the accessor. * @param feeAIn Fraction of the pool swap amount for tokenA-input swaps * that is retained as an LP in D18 scale. * @param feeBIn Fraction of the pool swap amount for tokenB-input swaps * that is retained as an LP in D18 scale. * @param tickSpacing Tick spacing of pool where 1.0001^tickSpacing is the * bin width. * @param lookback Pool lookback in seconds. * @param tokenA Address of tokenA. * @param tokenB Address of tokenB. * @param activeTick Tick position that contains the active bins. * @param kinds 1-15 number to represent the active kinds * 0b0001 = static; * 0b0010 = right; * 0b0100 = left; * 0b1000 = both. * E.g. a pool with all 4 modes will have kinds = b1111 = 15 * @param accessor only address that can access the pool's public permissioned write functions. * @param permissionedLiquidity If true, then only accessor can call * pool's liquidity management functions: `flashLoan`, * `migrateBinsUpstack`, `addLiquidity`, `removeLiquidity`. * @param permissionedSwap If true, then only accessor can call * pool's swap function. */ function createPermissioned( uint64 feeAIn, uint64 feeBIn, uint16 tickSpacing, uint32 lookback, IERC20 tokenA, IERC20 tokenB, int32 activeTick, uint8 kinds, address accessor, bool permissionedLiquidity, bool permissionedSwap ) external returns (IMaverickV2Pool pool); /** * @notice Update the protocol fee ratio for a pool. Can be called * permissionlessly allowing any user to sync the pool protocol fee value * with the factory protocol fee value. * @param pool The pool for which to update. */ function updateProtocolFeeRatioForPool(IMaverickV2Pool pool) external; /** * @notice Update the protocol lending fee rate for a pool. Can be called * permissionlessly allowing any user to sync the pool protocol lending fee * rate value with the factory value. * @param pool The pool for which to update. */ function updateProtocolLendingFeeRateForPool(IMaverickV2Pool pool) external; /** * @notice Claim protocol fee for a pool and transfer it to the protocolFeeReceiver. * @param pool The pool from which to claim the protocol fee. * @param isTokenA A boolean indicating whether tokenA (true) or tokenB * (false) is being collected. */ function claimProtocolFeeForPool(IMaverickV2Pool pool, bool isTokenA) external; /** * @notice Claim protocol fee for a pool and transfer it to the protocolFeeReceiver. * @param pool The pool from which to claim the protocol fee. */ function claimProtocolFeeForPool(IMaverickV2Pool pool) external; /** * @notice Bool indicating whether the pool was deployed from this factory. */ function isFactoryPool(IMaverickV2Pool pool) external view returns (bool); /** * @notice Address that receives the protocol fee when users call * `claimProtocolFeeForPool`. */ function protocolFeeReceiver() external view returns (address); /** * @notice Lookup a pool for given parameters. * * @dev options bit map of kinds and function permissions * 0b000001 = static; * 0b000010 = right; * 0b000100 = left; * 0b001000 = both; * 0b010000 = liquidity functions are permissioned * 0b100000 = swap function is permissioned */ function lookupPermissioned( uint256 feeAIn, uint256 feeBIn, uint256 tickSpacing, uint256 lookback, IERC20 tokenA, IERC20 tokenB, uint8 options, address accessor ) external view returns (IMaverickV2Pool); /** * @notice Lookup a pool for given parameters. */ function lookupPermissioned( IERC20 _tokenA, IERC20 _tokenB, address accessor, uint256 startIndex, uint256 endIndex ) external view returns (IMaverickV2Pool[] memory pools); /** * @notice Lookup a pool for given parameters. */ function lookupPermissioned( uint256 startIndex, uint256 endIndex ) external view returns (IMaverickV2Pool[] memory pools); /** * @notice Lookup a pool for given parameters. */ function lookup( uint256 feeAIn, uint256 feeBIn, uint256 tickSpacing, uint256 lookback, IERC20 tokenA, IERC20 tokenB, uint8 kinds ) external view returns (IMaverickV2Pool); /** * @notice Lookup a pool for given parameters. */ function lookup( IERC20 _tokenA, IERC20 _tokenB, uint256 startIndex, uint256 endIndex ) external view returns (IMaverickV2Pool[] memory pools); /** * @notice Lookup a pool for given parameters. */ function lookup(uint256 startIndex, uint256 endIndex) external view returns (IMaverickV2Pool[] memory pools); /** * @notice Count of permissionless pools. */ function poolCount() external view returns (uint256 _poolCount); /** * @notice Count of permissioned pools. */ function poolPermissionedCount() external view returns (uint256 _poolCount); /** * @notice Count of pools for a given accessor and token pair. For * permissionless pools, pass `accessor = address(0)`. */ function poolByTokenCount( IERC20 _tokenA, IERC20 _tokenB, address accessor ) external view returns (uint256 _poolCount); /** * @notice Get the current factory owner. */ function owner() external view returns (address); /** * @notice Proportion of protocol fee to collect on each swap. Value is in * 3-decimal format with a maximum value of 0.25e3. */ function protocolFeeRatioD3() external view returns (uint8); /** * @notice Fee rate charged by the protocol for flashloans. Value is in * 18-decimal format with a maximum value of 0.02e18. */ function protocolLendingFeeRateD18() external view returns (uint256); }
// SPDX-License-Identifier: GPL-2.0-or-later // As the copyright holder of this work, Ubiquity Labs retains // the right to distribute, use, and modify this code under any license of // their choosing, in addition to the terms of the GPL-v2 or later. pragma solidity ^0.8.25; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IMaverickV2Factory} from "./IMaverickV2Factory.sol"; interface IMaverickV2Pool { error PoolZeroLiquidityAdded(); error PoolMinimumLiquidityNotMet(); error PoolLocked(); error PoolInvalidFee(); error PoolTicksNotSorted(uint256 index, int256 previousTick, int256 tick); error PoolTicksAmountsLengthMismatch(uint256 ticksLength, uint256 amountsLength); error PoolBinIdsAmountsLengthMismatch(uint256 binIdsLength, uint256 amountsLength); error PoolKindNotSupported(uint256 kinds, uint256 kind); error PoolInsufficientBalance(uint256 deltaLpAmount, uint256 accountBalance); error PoolReservesExceedMaximum(uint256 amount); error PoolValueExceedsBits(uint256 amount, uint256 bits); error PoolTickMaxExceeded(uint256 tick); error PoolMigrateBinFirst(); error PoolCurrentTickBeyondSwapLimit(int32 startingTick); error PoolSenderNotAccessor(address sender_, address accessor); error PoolSenderNotFactory(address sender_, address accessor); error PoolFunctionNotImplemented(); error PoolTokenNotSolvent(uint256 internalReserve, uint256 tokenBalance, IERC20 token); event PoolSwap(address sender, address recipient, SwapParams params, uint256 amountIn, uint256 amountOut); event PoolAddLiquidity( address sender, address recipient, uint256 subaccount, AddLiquidityParams params, uint256 tokenAAmount, uint256 tokenBAmount, uint32[] binIds ); event PoolMigrateBinsUpStack(address sender, uint32 binId, uint32 maxRecursion); event PoolRemoveLiquidity( address sender, address recipient, uint256 subaccount, RemoveLiquidityParams params, uint256 tokenAOut, uint256 tokenBOut ); event PoolSetVariableFee(uint256 newFeeAIn, uint256 newFeeBIn); /** * @notice Tick state parameters. */ struct TickState { uint128 reserveA; uint128 reserveB; uint128 totalSupply; uint32[4] binIdsByTick; } /** * @notice Tick data parameters. * @param currentReserveA Current reserve of token A. * @param currentReserveB Current reserve of token B. * @param currentLiquidity Current liquidity amount. */ struct TickData { uint256 currentReserveA; uint256 currentReserveB; uint256 currentLiquidity; } /** * @notice Bin state parameters. * @param mergeBinBalance LP token balance that this bin possesses of the merge bin. * @param mergeId Bin ID of the bin that this bin has merged into. * @param totalSupply Total amount of LP tokens in this bin. * @param kind One of the 4 kinds (0=static, 1=right, 2=left, 3=both). * @param tick The lower price tick of the bin in its current state. * @param tickBalance Balance of the tick. */ struct BinState { uint128 mergeBinBalance; uint128 tickBalance; uint128 totalSupply; uint8 kind; int32 tick; uint32 mergeId; } /** * @notice Parameters for swap. * @param amount Amount of the token that is either the input if exactOutput is false * or the output if exactOutput is true. * @param tokenAIn Boolean indicating whether tokenA is the input. * @param exactOutput Boolean indicating whether the amount specified is * the exact output amount (true). * @param tickLimit The furthest tick a swap will execute in. If no limit * is desired, value should be set to type(int32).max for a tokenAIn swap * and type(int32).min for a swap where tokenB is the input. */ struct SwapParams { uint256 amount; bool tokenAIn; bool exactOutput; int32 tickLimit; } /** * @notice Parameters associated with adding liquidity. * @param kind One of the 4 kinds (0=static, 1=right, 2=left, 3=both). * @param ticks Array of ticks to add liquidity to. * @param amounts Array of bin LP amounts to add. */ struct AddLiquidityParams { uint8 kind; int32[] ticks; uint128[] amounts; } /** * @notice Parameters for each bin that will have liquidity removed. * @param binIds Index array of the bins losing liquidity. * @param amounts Array of bin LP amounts to remove. */ struct RemoveLiquidityParams { uint32[] binIds; uint128[] amounts; } /** * @notice State of the pool. * @param reserveA Pool tokenA balanceOf at end of last operation * @param reserveB Pool tokenB balanceOf at end of last operation * @param lastTwaD8 Value of log time weighted average price at last block. * Value is 8-decimal scale and is in the fractional tick domain. E.g. a * value of 12.3e8 indicates the TWAP was 3/10ths of the way into the 12th * tick. * @param lastLogPriceD8 Value of log price at last block. Value is * 8-decimal scale and is in the fractional tick domain. E.g. a value of * 12.3e8 indicates the price was 3/10ths of the way into the 12th tick. * @param lastTimestamp Last block.timestamp value in seconds for latest * swap transaction. * @param activeTick Current tick position that contains the active bins. * @param isLocked Pool isLocked, E.g., locked or unlocked; isLocked values * defined in Pool.sol. * @param binCounter Index of the last bin created. * @param protocolFeeRatioD3 Ratio of the swap fee that is kept for the * protocol. */ struct State { uint128 reserveA; uint128 reserveB; int64 lastTwaD8; int64 lastLogPriceD8; uint40 lastTimestamp; int32 activeTick; bool isLocked; uint32 binCounter; uint8 protocolFeeRatioD3; } /** * @notice Internal data used for data passing between Pool and Bin code. */ struct BinDelta { uint128 deltaA; uint128 deltaB; } /** * @notice 1-15 number to represent the active kinds. * @notice 0b0001 = static; * @notice 0b0010 = right; * @notice 0b0100 = left; * @notice 0b1000 = both; * * E.g. a pool with all 4 modes will have kinds = b1111 = 15 */ function kinds() external view returns (uint8 _kinds); /** * @notice Returns whether a pool has permissioned functions. If true, the * `accessor()` of the pool can set the pool fees. Other functions in the * pool may also be permissioned; whether or not they are can be determined * through calls to `permissionedLiquidity()` and `permissionedSwap()`. */ function permissionedPool() external view returns (bool _permissionedPool); /** * @notice Returns whether a pool has permissioned liquidity management * functions. If true, the pool is incompatible with permissioned pool * liquidity management infrastructure. */ function permissionedLiquidity() external view returns (bool _permissionedLiquidity); /** * @notice Returns whether a pool has a permissioned swap functions. If * true, the pool is incompatible with permissioned pool swap router * infrastructure. */ function permissionedSwap() external view returns (bool _permissionedSwap); /** * @notice Pool swap fee for the given direction (A-in or B-in swap) in * 18-decimal format. E.g. 0.01e18 is a 1% swap fee. */ function fee(bool tokenAIn) external view returns (uint256); /** * @notice TickSpacing of pool where 1.0001^tickSpacing is the bin width. */ function tickSpacing() external view returns (uint256); /** * @notice Lookback period of pool in seconds. */ function lookback() external view returns (uint256); /** * @notice Address of Pool accessor. This is Zero address for * permissionless pools. */ function accessor() external view returns (address); /** * @notice Pool tokenA. Address of tokenA is such that tokenA < tokenB. */ function tokenA() external view returns (IERC20); /** * @notice Pool tokenB. */ function tokenB() external view returns (IERC20); /** * @notice Deploying factory of the pool and also contract that has ability * to set and collect protocol fees for the pool. */ function factory() external view returns (IMaverickV2Factory); /** * @notice Most significant bit of scale value is a flag to indicate whether * tokenA has more or less than 18 decimals. Scale is used in conjuction * with Math.toScale/Math.fromScale functions to convert from token amounts * to D18 scale internal pool accounting. */ function tokenAScale() external view returns (uint256); /** * @notice Most significant bit of scale value is a flag to indicate whether * tokenA has more or less than 18 decimals. Scale is used in conjuction * with Math.toScale/Math.fromScale functions to convert from token amounts * to D18 scale internal pool accounting. */ function tokenBScale() external view returns (uint256); /** * @notice ID of bin at input tick position and kind. */ function binIdByTickKind(int32 tick, uint256 kind) external view returns (uint32); /** * @notice Accumulated tokenA protocol fee. */ function protocolFeeA() external view returns (uint128); /** * @notice Accumulated tokenB protocol fee. */ function protocolFeeB() external view returns (uint128); /** * @notice Lending fee rate on flash loans. */ function lendingFeeRateD18() external view returns (uint256); /** * @notice External function to get the current time-weighted average price. */ function getCurrentTwa() external view returns (int256); /** * @notice External function to get the state of the pool. */ function getState() external view returns (State memory); /** * @notice Return state of Bin at input binId. */ function getBin(uint32 binId) external view returns (BinState memory bin); /** * @notice Return state of Tick at input tick position. */ function getTick(int32 tick) external view returns (TickState memory tickState); /** * @notice Retrieves the balance of a user within a bin. * @param user The user's address. * @param subaccount The subaccount for the user. * @param binId The ID of the bin. */ function balanceOf(address user, uint256 subaccount, uint32 binId) external view returns (uint128 lpToken); /** * @notice Add liquidity to a pool. This function allows users to deposit * tokens into a liquidity pool. * @dev This function will call `maverickV2AddLiquidityCallback` on the * calling contract to collect the tokenA/tokenB payment. * @param recipient The account that will receive credit for the added liquidity. * @param subaccount The account that will receive credit for the added liquidity. * @param params Parameters containing the details for adding liquidity, * such as token types and amounts. * @param data Bytes information that gets passed to the callback. * @return tokenAAmount The amount of token A added to the pool. * @return tokenBAmount The amount of token B added to the pool. * @return binIds An array of bin IDs where the liquidity is stored. */ function addLiquidity( address recipient, uint256 subaccount, AddLiquidityParams calldata params, bytes calldata data ) external returns (uint256 tokenAAmount, uint256 tokenBAmount, uint32[] memory binIds); /** * @notice Removes liquidity from the pool. * @dev Liquidy can only be removed from a bin that is either unmerged or * has a mergeId of an unmerged bin. If a bin is merged more than one * level deep, it must be migrated up the merge stack to the root bin * before liquidity removal. * @param recipient The address to receive the tokens. * @param subaccount The subaccount for the recipient. * @param params The parameters for removing liquidity. * @return tokenAOut The amount of token A received. * @return tokenBOut The amount of token B received. */ function removeLiquidity( address recipient, uint256 subaccount, RemoveLiquidityParams calldata params ) external returns (uint256 tokenAOut, uint256 tokenBOut); /** * @notice Migrate bins up the linked list of merged bins so that its * mergeId is the currrent active bin. * @dev Liquidy can only be removed from a bin that is either unmerged or * has a mergeId of an unmerged bin. If a bin is merged more than one * level deep, it must be migrated up the merge stack to the root bin * before liquidity removal. * @param binId The ID of the bin to migrate. * @param maxRecursion The maximum recursion depth for the migration. */ function migrateBinUpStack(uint32 binId, uint32 maxRecursion) external; /** * @notice Swap tokenA/tokenB assets in the pool. The swap user has two * options for funding their swap. * - The user can push the input token amount to the pool before calling * the swap function. In order to avoid having the pool call the callback, * the user should pass a zero-length `data` bytes object with the swap * call. * - The user can send the input token amount to the pool when the pool * calls the `maverickV2SwapCallback` function on the calling contract. * That callback has input parameters that specify the token address of the * input token, the input and output amounts, and the bytes data sent to * the swap function. * @dev If the users elects to do a callback-based swap, the output * assets will be sent before the callback is called, allowing the user to * execute flash swaps. However, the pool does have reentrancy protection, * so a swapper will not be able to interact with the same pool again * while they are in the callback function. * @param recipient The address to receive the output tokens. * @param params Parameters containing the details of the swap * @param data Bytes information that gets passed to the callback. */ function swap( address recipient, SwapParams memory params, bytes calldata data ) external returns (uint256 amountIn, uint256 amountOut); /** * @notice Loan tokenA/tokenB assets from the pool to recipient. The fee * rate of a loan is determined by `lendingFeeRateD18`, which is set at the * protocol level by the factory. This function calls * `maverickV2FlashLoanCallback` on the calling contract. At the end of * the callback, the caller must pay back the loan with fee (if there is a * fee). * @param recipient The address to receive the loaned tokens. * @param amountB Loan amount of tokenA sent to recipient. * @param amountB Loan amount of tokenB sent to recipient. * @param data Bytes information that gets passed to the callback. */ function flashLoan( address recipient, uint256 amountA, uint256 amountB, bytes calldata data ) external returns (uint128 lendingFeeA, uint128 lendingFeeB); /** * @notice Sets fee for permissioned pools. May only be called by the * accessor. */ function setFee(uint256 newFeeAIn, uint256 newFeeBIn) external; }
// SPDX-License-Identifier: GPL-2.0-or-later // As the copyright holder of this work, Ubiquity Labs retains // the right to distribute, use, and modify this code under any license of // their choosing, in addition to the terms of the GPL-v2 or later. pragma solidity ^0.8.25; // factory contraints on pools uint8 constant MAX_PROTOCOL_FEE_RATIO_D3 = 0.25e3; // 25% uint256 constant MAX_PROTOCOL_LENDING_FEE_RATE_D18 = 0.02e18; // 2% uint64 constant MAX_POOL_FEE_D18 = 0.9e18; // 90% uint64 constant MIN_LOOKBACK = 1 seconds; uint64 constant MAX_TICK_SPACING = 10_000; // pool constraints uint8 constant NUMBER_OF_KINDS = 4; int32 constant NUMBER_OF_KINDS_32 = int32(int8(NUMBER_OF_KINDS)); uint256 constant MAX_TICK = 322_378; // max price 1e14 in D18 scale int32 constant MAX_TICK_32 = int32(int256(MAX_TICK)); int32 constant MIN_TICK_32 = int32(-int256(MAX_TICK)); uint256 constant MAX_BINS_TO_MERGE = 3; uint128 constant MINIMUM_LIQUIDITY = 1e8; // accessor named constants uint8 constant ALL_KINDS_MASK = 0xF; // 0b1111 uint8 constant PERMISSIONED_LIQUIDITY_MASK = 0x10; // 0b010000 uint8 constant PERMISSIONED_SWAP_MASK = 0x20; // 0b100000 uint8 constant OPTIONS_MASK = ALL_KINDS_MASK | PERMISSIONED_LIQUIDITY_MASK | PERMISSIONED_SWAP_MASK; // 0b111111 // named values address constant MERGED_LP_BALANCE_ADDRESS = address(0); uint256 constant MERGED_LP_BALANCE_SUBACCOUNT = 0; uint128 constant ONE = 1e18; uint128 constant ONE_SQUARED = 1e36; int256 constant INT256_ONE = 1e18; uint256 constant ONE_D8 = 1e8; uint256 constant ONE_D3 = 1e3; int40 constant INT_ONE_D8 = 1e8; int40 constant HALF_TICK_D8 = 0.5e8; uint8 constant DEFAULT_DECIMALS = 18; uint256 constant DEFAULT_SCALE = 1; bytes constant EMPTY_PRICE_BREAKS = hex"010000000000000000000000";
// SPDX-License-Identifier: GPL-2.0-or-later // As the copyright holder of this work, Ubiquity Labs retains // the right to distribute, use, and modify this code under any license of // their choosing, in addition to the terms of the GPL-v2 or later. pragma solidity ^0.8.25; import {Math as OzMath} from "@openzeppelin/contracts/utils/math/Math.sol"; import {ONE, DEFAULT_SCALE, DEFAULT_DECIMALS, INT_ONE_D8, ONE_SQUARED} from "./Constants.sol"; /** * @notice Math functions. */ library Math { /** * @notice Returns the lesser of two values. * @param x First uint256 value. * @param y Second uint256 value. */ function min(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly ("memory-safe") { z := xor(x, mul(xor(x, y), lt(y, x))) } } /** * @notice Returns the lesser of two uint128 values. * @param x First uint128 value. * @param y Second uint128 value. */ function min128(uint128 x, uint128 y) internal pure returns (uint128 z) { assembly ("memory-safe") { z := xor(x, mul(xor(x, y), lt(y, x))) } } /** * @notice Returns the lesser of two int256 values. * @param x First int256 value. * @param y Second int256 value. */ function min(int256 x, int256 y) internal pure returns (int256 z) { assembly ("memory-safe") { z := xor(x, mul(xor(x, y), slt(y, x))) } } /** * @notice Returns the greater of two uint256 values. * @param x First uint256 value. * @param y Second uint256 value. */ function max(uint256 x, uint256 y) internal pure returns (uint256 z) { assembly ("memory-safe") { z := xor(x, mul(xor(x, y), gt(y, x))) } } /** * @notice Returns the greater of two int256 values. * @param x First int256 value. * @param y Second int256 value. */ function max(int256 x, int256 y) internal pure returns (int256 z) { assembly ("memory-safe") { z := xor(x, mul(xor(x, y), sgt(y, x))) } } /** * @notice Returns the greater of two uint128 values. * @param x First uint128 value. * @param y Second uint128 value. */ function max128(uint128 x, uint128 y) internal pure returns (uint128 z) { assembly ("memory-safe") { z := xor(x, mul(xor(x, y), gt(y, x))) } } /** * @notice Thresholds a value to be within the specified bounds. * @param value The value to bound. * @param lowerLimit The minimum allowable value. * @param upperLimit The maximum allowable value. */ function boundValue( uint256 value, uint256 lowerLimit, uint256 upperLimit ) internal pure returns (uint256 outputValue) { outputValue = min(max(value, lowerLimit), upperLimit); } /** * @notice Returns the difference between two uint128 values or zero if the result would be negative. * @param x The minuend. * @param y The subtrahend. */ function clip128(uint128 x, uint128 y) internal pure returns (uint128) { unchecked { return x < y ? 0 : x - y; } } /** * @notice Returns the difference between two uint256 values or zero if the result would be negative. * @param x The minuend. * @param y The subtrahend. */ function clip(uint256 x, uint256 y) internal pure returns (uint256) { unchecked { return x < y ? 0 : x - y; } } /** * @notice Divides one uint256 by another, rounding down to the nearest * integer. * @param x The dividend. * @param y The divisor. */ function divFloor(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivFloor(x, ONE, y); } /** * @notice Divides one uint256 by another, rounding up to the nearest integer. * @param x The dividend. * @param y The divisor. */ function divCeil(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivCeil(x, ONE, y); } /** * @notice Multiplies two uint256 values and then divides by ONE, rounding down. * @param x The multiplicand. * @param y The multiplier. */ function mulFloor(uint256 x, uint256 y) internal pure returns (uint256) { return OzMath.mulDiv(x, y, ONE); } /** * @notice Multiplies two uint256 values and then divides by ONE, rounding up. * @param x The multiplicand. * @param y The multiplier. */ function mulCeil(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivCeil(x, y, ONE); } /** * @notice Calculates the multiplicative inverse of a uint256, rounding down. * @param x The value to invert. */ function invFloor(uint256 x) internal pure returns (uint256) { unchecked { return ONE_SQUARED / x; } } /** * @notice Calculates the multiplicative inverse of a uint256, rounding up. * @param denominator The value to invert. */ function invCeil(uint256 denominator) internal pure returns (uint256 z) { assembly ("memory-safe") { // divide z - 1 by the denominator and add 1. z := add(div(sub(ONE_SQUARED, 1), denominator), 1) } } /** * @notice Multiplies two uint256 values and divides by a third, rounding down. * @param x The multiplicand. * @param y The multiplier. * @param k The divisor. */ function mulDivFloor(uint256 x, uint256 y, uint256 k) internal pure returns (uint256 result) { result = OzMath.mulDiv(x, y, max(1, k)); } /** * @notice Multiplies two uint256 values and divides by a third, rounding up if there's a remainder. * @param x The multiplicand. * @param y The multiplier. * @param k The divisor. */ function mulDivCeil(uint256 x, uint256 y, uint256 k) internal pure returns (uint256 result) { result = mulDivFloor(x, y, k); if (mulmod(x, y, max(1, k)) != 0) result = result + 1; } /** * @notice Multiplies two uint256 values and divides by a third, rounding * down. Will revert if `x * y` is larger than `type(uint256).max`. * @param x The first operand for multiplication. * @param y The second operand for multiplication. * @param denominator The divisor after multiplication. */ function mulDivDown(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 z) { assembly ("memory-safe") { // Store x * y in z for now. z := mul(x, y) if iszero(denominator) { denominator := 1 } if iszero(or(iszero(x), eq(div(z, x), y))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } /** * @notice Multiplies two uint256 values and divides by a third, rounding * up. Will revert if `x * y` is larger than `type(uint256).max`. * @param x The first operand for multiplication. * @param y The second operand for multiplication. * @param denominator The divisor after multiplication. */ function mulDivUp(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 z) { assembly ("memory-safe") { // Store x * y in z for now. z := mul(x, y) if iszero(denominator) { denominator := 1 } if iszero(or(iszero(x), eq(div(z, x), y))) { revert(0, 0) } // First, divide z - 1 by the denominator and add 1. // We allow z - 1 to underflow if z is 0, because we multiply the // end result by 0 if z is zero, ensuring we return 0 if z is zero. z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1)) } } /** * @notice Multiplies a uint256 by another and divides by a constant, * rounding down. Will revert if `x * y` is larger than * `type(uint256).max`. * @param x The multiplicand. * @param y The multiplier. */ function mulDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, ONE); } /** * @notice Divides a uint256 by another, rounding down the result. Will * revert if `x * 1e18` is larger than `type(uint256).max`. * @param x The dividend. * @param y The divisor. */ function divDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, ONE, y); } /** * @notice Divides a uint256 by another, rounding up the result. Will * revert if `x * 1e18` is larger than `type(uint256).max`. * @param x The dividend. * @param y The divisor. */ function divUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, ONE, y); } /** * @notice Scales a number based on a difference in decimals from a default. * @param decimals The new decimal precision. */ function scale(uint8 decimals) internal pure returns (uint256) { unchecked { if (decimals == DEFAULT_DECIMALS) { return DEFAULT_SCALE; } else { return 10 ** (DEFAULT_DECIMALS - decimals); } } } /** * @notice Adjusts a scaled amount to the token decimal scale. * @param amount The scaled amount. * @param scaleFactor The scaling factor to adjust by. * @param ceil Whether to round up (true) or down (false). */ function ammScaleToTokenScale(uint256 amount, uint256 scaleFactor, bool ceil) internal pure returns (uint256 z) { unchecked { if (scaleFactor == DEFAULT_SCALE || amount == 0) { return amount; } else { if (!ceil) return amount / scaleFactor; assembly ("memory-safe") { z := add(div(sub(amount, 1), scaleFactor), 1) } } } } /** * @notice Adjusts a token amount to the D18 AMM scale. * @param amount The amount in token scale. * @param scaleFactor The scale factor for adjustment. */ function tokenScaleToAmmScale(uint256 amount, uint256 scaleFactor) internal pure returns (uint256) { if (scaleFactor == DEFAULT_SCALE) { return amount; } else { return amount * scaleFactor; } } /** * @notice Returns the absolute value of a signed 32-bit integer. * @param x The integer to take the absolute value of. */ function abs32(int32 x) internal pure returns (uint32) { unchecked { return uint32(x < 0 ? -x : x); } } /** * @notice Returns the absolute value of a signed 256-bit integer. * @param x The integer to take the absolute value of. */ function abs(int256 x) internal pure returns (uint256) { unchecked { return uint256(x < 0 ? -x : x); } } /** * @notice Calculates the integer square root of a uint256 rounded down. * @param x The number to take the square root of. */ function sqrt(uint256 x) internal pure returns (uint256 z) { // from https://github.com/transmissions11/solmate/blob/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/FixedPointMathLib.sol assembly ("memory-safe") { let y := x z := 181 if iszero(lt(y, 0x10000000000000000000000000000000000)) { y := shr(128, y) z := shl(64, z) } if iszero(lt(y, 0x1000000000000000000)) { y := shr(64, y) z := shl(32, z) } if iszero(lt(y, 0x10000000000)) { y := shr(32, y) z := shl(16, z) } if iszero(lt(y, 0x1000000)) { y := shr(16, y) z := shl(8, z) } z := shr(18, mul(z, add(y, 65536))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := sub(z, lt(div(x, z), z)) } } /** * @notice Computes the floor of a D8-scaled number as an int32, ignoring * potential overflow in the cast. * @param val The D8-scaled number. */ function floorD8Unchecked(int256 val) internal pure returns (int32) { int32 val32; bool check; unchecked { val32 = int32(val / INT_ONE_D8); check = (val < 0 && val % INT_ONE_D8 != 0); } return check ? val32 - 1 : val32; } }
// SPDX-License-Identifier: GPL-2.0-or-later // As the copyright holder of this work, Ubiquity Labs retains // the right to distribute, use, and modify this code under any license of // their choosing, in addition to the terms of the GPL-v2 or later. pragma solidity ^0.8.25; import {SafeCast as Cast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import {IMaverickV2Pool} from "../interfaces/IMaverickV2Pool.sol"; import {TickMath} from "./TickMath.sol"; import {Math} from "./Math.sol"; /** * @notice Library of pool functions. */ library PoolLib { using Cast for uint256; struct AddLiquidityInfo { uint256 deltaA; uint256 deltaB; bool tickLtActive; uint256 tickSpacing; int32 tick; } /** * @notice Check to ensure that the ticks are in ascending order and amount * array is same length as tick array. * @param ticks An array of int32 values representing ticks to be checked. * @param amountsLength Amount array length. */ function uniqueOrderedTicksCheck(int32[] memory ticks, uint256 amountsLength) internal pure { unchecked { if (ticks.length != amountsLength) revert IMaverickV2Pool.PoolTicksAmountsLengthMismatch(ticks.length, amountsLength); int32 lastTick = type(int32).min; for (uint256 i; i < ticks.length; ) { if (ticks[i] <= lastTick) revert IMaverickV2Pool.PoolTicksNotSorted(i, lastTick, ticks[i]); lastTick = ticks[i]; i = i + 1; } } } /** * @notice Compute bin reserves assuming the bin is not merged; not accurate * reflection of reserves for merged bins. * @param bin The storage reference to the state for this bin. * @param tick The memory reference to the state for this tick. * @return reserveA The reserve amount for token A. * @return reserveB The reserve amount for token B. */ function binReserves( IMaverickV2Pool.BinState storage bin, IMaverickV2Pool.TickState memory tick ) internal view returns (uint128 reserveA, uint128 reserveB) { return binReserves(bin.tickBalance, tick.reserveA, tick.reserveB, tick.totalSupply); } /** * @notice Compute bin reserves assuming the bin is not merged; not accurate * reflection of reserves for merged bins. * @param tickBalance Bin's balance in the tick. * @param tickReserveA Tick's tokenA reserves. * @param tickReserveB Tick's tokenB reserves. * @param tickTotalSupply Tick total supply of bin balances. */ function binReserves( uint128 tickBalance, uint128 tickReserveA, uint128 tickReserveB, uint128 tickTotalSupply ) internal pure returns (uint128 reserveA, uint128 reserveB) { if (tickTotalSupply != 0) { reserveA = reserveValue(tickReserveA, tickBalance, tickTotalSupply); reserveB = reserveValue(tickReserveB, tickBalance, tickTotalSupply); } } /** * @notice Reserves of a bin in a tick. * @param tickReserve Tick reserve amount in a given token. * @param tickBalance Bin's balance in the tick. * @param tickTotalSupply Tick total supply of bin balances. */ function reserveValue( uint128 tickReserve, uint128 tickBalance, uint128 tickTotalSupply ) internal pure returns (uint128 reserve) { reserve = Math.mulDivFloor(tickReserve, tickBalance, tickTotalSupply).toUint128(); reserve = Math.min128(tickReserve, reserve); } /** * @notice Calculate delta A, delta B, and delta Tick Balance based on delta * LP balance and the Tick/Bin state. */ function deltaTickBalanceFromDeltaLpBalance( uint256 binTickBalance, uint256 binTotalSupply, IMaverickV2Pool.TickState memory tickState, uint128 deltaLpBalance, AddLiquidityInfo memory addLiquidityInfo ) internal pure returns (uint256 deltaTickBalance) { unchecked { if (tickState.reserveA != 0 || tickState.reserveB != 0) { // if there are already reserves, then we just contribute pro rata // deltaLiquidity = deltaBinLP / binTS * binTickBalance / tickTS * tickL uint256 numerator = Math.max(1, binTickBalance) * uint256(deltaLpBalance); uint256 denominator = Math.max(1, tickState.totalSupply) * Math.max(1, binTotalSupply); addLiquidityInfo.deltaA = Math.mulDivCeil(tickState.reserveA, numerator, denominator); addLiquidityInfo.deltaB = Math.mulDivCeil(tickState.reserveB, numerator, denominator); } else { _setRequiredDeltaReservesForEmptyTick(deltaLpBalance, addLiquidityInfo); } // round down the amount credited to the tick; this could lead to a // small add amount getting zero reserves credit. deltaTickBalance = tickState.totalSupply == 0 ? deltaLpBalance : Math.mulDivDown(deltaLpBalance, Math.max(1, binTickBalance), binTotalSupply); } } /** * @notice Calculates deltaA = liquidity * (sqrt(upper) - sqrt(lower)) * @notice Calculates deltaB = liquidity / sqrt(lower) - liquidity / sqrt(upper), * @notice i.e. liquidity * (sqrt(upper) - sqrt(lower)) / (sqrt(upper) * sqrt(lower)) * @notice we set liquidity = deltaLpBalance / (1.0001^(tick * tickspacing) - 1) * @notice which simplifies the A/B amounts to: * @notice deltaA = deltaLpBalance * sqrt(lower) * @notice deltaB = deltaLpBalance / sqrt(upper) */ function _setRequiredDeltaReservesForEmptyTick( uint128 deltaLpBalance, AddLiquidityInfo memory addLiquidityInfo ) internal pure { // No reserves, so we will use deltaLpBalance as liquidity to be added. // In this logic branch, the tick is empty, so we know the tick will be // a one-asset add. (uint256 sqrtLowerTickPrice, uint256 sqrtUpperTickPrice) = TickMath.tickSqrtPrices( addLiquidityInfo.tickSpacing, addLiquidityInfo.tick ); addLiquidityInfo.deltaA = addLiquidityInfo.tickLtActive ? Math.mulCeil(deltaLpBalance, sqrtLowerTickPrice) : 0; addLiquidityInfo.deltaB = addLiquidityInfo.tickLtActive ? 0 : Math.divCeil(deltaLpBalance, sqrtUpperTickPrice); } }
// SPDX-License-Identifier: GPL-2.0-or-later // As the copyright holder of this work, Ubiquity Labs retains // the right to distribute, use, and modify this code under any license of // their choosing, in addition to the terms of the GPL-v2 or later. pragma solidity ^0.8.25; import {Math as OzMath} from "@openzeppelin/contracts/utils/math/Math.sol"; import {Math} from "./Math.sol"; import {MAX_TICK, ONE} from "./Constants.sol"; /** * @notice Math functions related to tick operations. */ library TickMath { using Math for uint256; error TickMaxExceeded(int256 tick); /** * @notice Compute the lower and upper sqrtPrice of a tick. * @param tickSpacing The tick spacing used for calculations. * @param _tick The input tick value. */ function tickSqrtPrices( uint256 tickSpacing, int32 _tick ) internal pure returns (uint256 sqrtLowerPrice, uint256 sqrtUpperPrice) { unchecked { sqrtLowerPrice = tickSqrtPrice(tickSpacing, _tick); sqrtUpperPrice = tickSqrtPrice(tickSpacing, _tick + 1); } } /** * @notice Compute the base tick value from the pool tick and the * tickSpacing. Revert if base tick is beyond the max tick boundary. * @param tickSpacing The tick spacing used for calculations. * @param _tick The input tick value. */ function subTickIndex(uint256 tickSpacing, int32 _tick) internal pure returns (uint32 subTick) { subTick = Math.abs32(_tick); subTick *= uint32(tickSpacing); if (subTick > MAX_TICK) { revert TickMaxExceeded(_tick); } } /** * @notice Calculate the square root price for a given tick and tick spacing. * @param tickSpacing The tick spacing used for calculations. * @param _tick The input tick value. * @return _result The square root price. */ function tickSqrtPrice(uint256 tickSpacing, int32 _tick) internal pure returns (uint256 _result) { unchecked { uint256 tick = subTickIndex(tickSpacing, _tick); uint256 ratio = tick & 0x1 != 0 ? 0xfffcb933bd6fad9d3af5f0b9f25db4d6 : 0x100000000000000000000000000000000; if (tick & 0x2 != 0) ratio = (ratio * 0xfff97272373d41fd789c8cb37ffcaa1c) >> 128; if (tick & 0x4 != 0) ratio = (ratio * 0xfff2e50f5f656ac9229c67059486f389) >> 128; if (tick & 0x8 != 0) ratio = (ratio * 0xffe5caca7e10e81259b3cddc7a064941) >> 128; if (tick & 0x10 != 0) ratio = (ratio * 0xffcb9843d60f67b19e8887e0bd251eb7) >> 128; if (tick & 0x20 != 0) ratio = (ratio * 0xff973b41fa98cd2e57b660be99eb2c4a) >> 128; if (tick & 0x40 != 0) ratio = (ratio * 0xff2ea16466c9838804e327cb417cafcb) >> 128; if (tick & 0x80 != 0) ratio = (ratio * 0xfe5dee046a99d51e2cc356c2f617dbe0) >> 128; if (tick & 0x100 != 0) ratio = (ratio * 0xfcbe86c7900aecf64236ab31f1f9dcb5) >> 128; if (tick & 0x200 != 0) ratio = (ratio * 0xf987a7253ac4d9194200696907cf2e37) >> 128; if (tick & 0x400 != 0) ratio = (ratio * 0xf3392b0822b88206f8abe8a3b44dd9be) >> 128; if (tick & 0x800 != 0) ratio = (ratio * 0xe7159475a2c578ef4f1d17b2b235d480) >> 128; if (tick & 0x1000 != 0) ratio = (ratio * 0xd097f3bdfd254ee83bdd3f248e7e785e) >> 128; if (tick & 0x2000 != 0) ratio = (ratio * 0xa9f746462d8f7dd10e744d913d033333) >> 128; if (tick & 0x4000 != 0) ratio = (ratio * 0x70d869a156ddd32a39e257bc3f50aa9b) >> 128; if (tick & 0x8000 != 0) ratio = (ratio * 0x31be135f97da6e09a19dc367e3b6da40) >> 128; if (tick & 0x10000 != 0) ratio = (ratio * 0x9aa508b5b7e5a9780b0cc4e25d61a56) >> 128; if (tick & 0x20000 != 0) ratio = (ratio * 0x5d6af8dedbcb3a6ccb7ce618d14225) >> 128; if (tick & 0x40000 != 0) ratio = (ratio * 0x2216e584f630389b2052b8db590e) >> 128; if (_tick > 0) ratio = type(uint256).max / ratio; _result = (ratio * ONE) >> 128; } } /** * @notice Calculate liquidity of a tick. * @param reserveA Tick reserve of token A. * @param reserveB Tick reserve of token B. * @param sqrtLowerTickPrice The square root price of the lower tick edge. * @param sqrtUpperTickPrice The square root price of the upper tick edge. */ function getTickL( uint256 reserveA, uint256 reserveB, uint256 sqrtLowerTickPrice, uint256 sqrtUpperTickPrice ) internal pure returns (uint256 liquidity) { // known: // - sqrt price values are different // - reserveA and reserveB fit in 128 bit // - sqrt price is in (1e-7, 1e7) // - D18 max for uint256 is 1.15e59 // - D18 min is 1e-18 unchecked { // diff is in (5e-12, 4e6); max tick spacing is 10_000 uint256 diff = sqrtUpperTickPrice - sqrtLowerTickPrice; // Need to maximize precision by shifting small values A and B up so // that they use more of the available bit range. Two constraints to // consider: we need A * B * diff / sqrtPrice to be bigger than 1e-18 // when the bump is not in play. This constrains the threshold for // bumping to be at least 77 bit; ie, either a or b needs 2^77 which // means that term A * B * diff / sqrtPrice > 1e-18. // // At the other end, the second constraint is that b^2 needs to fit in // a 256-bit number, so, post bump, the max reserve value needs to be // less than 6e22. With a 78-bit threshold and a 57-bit bump, we have A // and B are in (1.4e-1, 4.4e22 (2^(78+57))) with bump, and one of A or // B is at least 2^78 without the bump, but the other reserve value may // be as small as 1 wei. uint256 precisionBump = 0; if ((reserveA >> 78) == 0 && (reserveB >> 78) == 0) { precisionBump = 57; reserveA <<= precisionBump; reserveB <<= precisionBump; } if (reserveB == 0) return Math.divDown(reserveA, diff) >> precisionBump; if (reserveA == 0) return Math.mulDivDown(reserveB.mulDown(sqrtLowerTickPrice), sqrtUpperTickPrice, diff) >> precisionBump; // b is in (7.2e-9 (2^57 / 1e7 / 2), 2.8e29 (2^(78+57) * 1e7 / 2)) with bump // b is in a subset of the same range without bump uint256 b = (reserveA.divDown(sqrtUpperTickPrice) + reserveB.mulDown(sqrtLowerTickPrice)) >> 1; // b^2 is in (5.1e-17, 4.8e58); and will not overflow on either end; // A*B is in (3e-13 (2^78 / 1e18 * 1e-18), 1.9e45) without bump and is in a subset range with bump // A*B*diff/sqrtUpper is in (1.5e-17 (3e-13 * 5e-12 * 1e7), 7.6e58); // Since b^2 is at the upper edge of the precision range, we are not // able to multiply the argument of the sqrt by 1e18, instead, we move // this factor outside of the sqrt. The resulting loss of precision // means that this liquidity value is a lower bound on the tick // liquidity return OzMath.mulDiv( b + Math.sqrt( (OzMath.mulDiv(b, b, ONE) + OzMath.mulDiv(reserveB.mulFloor(reserveA), diff, sqrtUpperTickPrice)) ) * 1e9, sqrtUpperTickPrice, diff ) >> precisionBump; } } /** * @notice Calculate square root price of a tick. Returns left edge of the * tick if the tick has no reserves. * @param reserveA Tick reserve of token A. * @param reserveB Tick reserve of token B. * @param sqrtLowerTickPrice The square root price of the lower tick edge. * @param sqrtUpperTickPrice The square root price of the upper tick edge. * @return sqrtPrice The calculated square root price. */ function getSqrtPrice( uint256 reserveA, uint256 reserveB, uint256 sqrtLowerTickPrice, uint256 sqrtUpperTickPrice, uint256 liquidity ) internal pure returns (uint256 sqrtPrice) { unchecked { if (reserveA == 0) { return sqrtLowerTickPrice; } if (reserveB == 0) { return sqrtUpperTickPrice; } sqrtPrice = Math.sqrt( ONE * (reserveA + liquidity.mulDown(sqrtLowerTickPrice)).divDown( reserveB + liquidity.divDown(sqrtUpperTickPrice) ) ); sqrtPrice = Math.boundValue(sqrtPrice, sqrtLowerTickPrice, sqrtUpperTickPrice); } } /** * @notice Calculate square root price of a tick. Returns left edge of the * tick if the tick has no reserves. * @param reserveA Tick reserve of token A. * @param reserveB Tick reserve of token B. * @param sqrtLowerTickPrice The square root price of the lower tick edge. * @param sqrtUpperTickPrice The square root price of the upper tick edge. * @return sqrtPrice The calculated square root price. * @return liquidity The calculated liquidity. */ function getTickSqrtPriceAndL( uint256 reserveA, uint256 reserveB, uint256 sqrtLowerTickPrice, uint256 sqrtUpperTickPrice ) internal pure returns (uint256 sqrtPrice, uint256 liquidity) { liquidity = getTickL(reserveA, reserveB, sqrtLowerTickPrice, sqrtUpperTickPrice); sqrtPrice = getSqrtPrice(reserveA, reserveB, sqrtLowerTickPrice, sqrtUpperTickPrice, liquidity); } }
// SPDX-License-Identifier: GPL-2.0-or-later // As the copyright holder of this work, Ubiquity Labs retains // the right to distribute, use, and modify this code under any license of // their choosing, in addition to the terms of the GPL-v2 or later. pragma solidity ^0.8.25; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /** * @notice Low-gas transfer functions. */ library TransferLib { error TransferFailed(IERC20 token, address to, uint256 amount); error TransferFromFailed(IERC20 token, address from, address to, uint256 amount); // implementation adapted from // https://github.com/transmissions11/solmate/blob/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/SafeTransferLib.sol /** * @notice Transfer token amount. Amount is sent from caller address to `to` address. */ function transfer(IERC20 token, address to, uint256 amount) internal { bool success; assembly ("memory-safe") { // We'll write our calldata to this slot below, but restore it later. let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(memPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) // Append arguments. Addresses are assumed clean. Transfer will fail otherwise. mstore(add(memPointer, 0x4), to) mstore(add(memPointer, 0x24), amount) // Append the "amount" argument. // 68 bytes total // fail if reverted; only allocate 32 bytes for return to ensure we // only use mem slot 0 which is scatch space and memory safe to use. success := call(gas(), token, 0, memPointer, 68, 0, 32) // handle transfers that return 1/true and ensure the value is from // the return and not dirty bits left in the scratch space. let returnedOne := and(eq(mload(0), 1), gt(returndatasize(), 31)) // handle transfers that return nothing let noReturn := iszero(returndatasize()) // good if didn't revert and the return is either empty or true success := and(success, or(returnedOne, noReturn)) } if (!success) revert TransferFailed(token, to, amount); } /** * @notice Transfer token amount. Amount is sent from `from` address to `to` address. */ function transferFrom(IERC20 token, address from, address to, uint256 amount) internal { bool success; assembly ("memory-safe") { // We'll write our calldata to this slot below, but restore it later. let memPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(memPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) // Append arguments. Addresses are assumed clean. Transfer will fail otherwise. mstore(add(memPointer, 0x4), from) // Append the "from" argument. mstore(add(memPointer, 0x24), to) // Append the "to" argument. mstore(add(memPointer, 0x44), amount) // Append the "amount" argument. // 100 bytes total // fail if reverted; only allocate 32 bytes for return to ensure we // only use mem slot 0 which is scatch space and memory safe to use. success := call(gas(), token, 0, memPointer, 100, 0, 32) // handle transfers that return 1/true and ensure the value is from // the return and not dirty bits left in the scratch space. let returnedOne := and(eq(mload(0), 1), gt(returndatasize(), 31)) // handle transfers that return nothing let noReturn := iszero(returndatasize()) // good if didn't revert and the return is either empty or true success := and(success, or(returnedOne, noReturn)) } if (!success) revert TransferFromFailed(token, from, to, amount); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; import {IChecks} from "./IChecks.sol"; import {PoolInspection} from "../libraries/PoolInspection.sol"; abstract contract Checks is IChecks { /// @inheritdoc IChecks function checkSqrtPrice(IMaverickV2Pool pool, uint256 minSqrtPrice, uint256 maxSqrtPrice) public payable { uint256 sqrtPrice = PoolInspection.poolSqrtPrice(pool); if (sqrtPrice < minSqrtPrice || sqrtPrice > maxSqrtPrice) revert PositionExceededPriceBounds(sqrtPrice, minSqrtPrice, maxSqrtPrice); } /// @inheritdoc IChecks function checkDeadline(uint256 deadline) public payable { if (block.timestamp > deadline) revert PositionDeadlinePassed(deadline, block.timestamp); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; interface IChecks { error PositionExceededPriceBounds(uint256 sqrtPrice, uint256 minSqrtPrice, uint256 maxSqrtPrice); error PositionDeadlinePassed(uint256 deadline, uint256 blockTimestamp); /** * @notice Function to check if the price of a pool is within specified bounds. * @param pool The MaverickV2Pool contract to check. * @param minSqrtPrice The minimum acceptable square root price. * @param maxSqrtPrice The maximum acceptable square root price. */ function checkSqrtPrice(IMaverickV2Pool pool, uint256 minSqrtPrice, uint256 maxSqrtPrice) external payable; /** * @notice Function to check if a given deadline has passed. * @param deadline The timestamp representing the deadline. */ function checkDeadline(uint256 deadline) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {ICallbackOperations} from "../routerbase/ICallbackOperations.sol"; import {IPushOperations} from "../routerbase/IPushOperations.sol"; import {IPayment} from "../paymentbase/IPayment.sol"; import {IChecks} from "../base/IChecks.sol"; /* solhint-disable no-empty-blocks */ interface IMaverickV2Router is IPayment, IChecks, ICallbackOperations, IPushOperations {}
// SPDX-License-Identifier: Unlicense pragma solidity ^0.8.25; // Adapted from https://github.com/GNSPS/solidity-bytes-utils/blob/1dff13ef21304eb3634cb9e7f86c119cf280bd35/contracts/BytesLib.sol library BytesLib { error BytesLibToBoolOutOfBounds(); error BytesLibToAddressOutOfBounds(); error BytesLibSliceOverflow(); error BytesLibSliceOutOfBounds(); error BytesLibInvalidLength(uint256 inputLength, uint256 expectedLength); function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) { // 31 is added to _length in assembly; need to check here that that // operation will not overflow if (_length > type(uint256).max - 31) revert BytesLibSliceOverflow(); if (_bytes.length < _start + _length) revert BytesLibSliceOutOfBounds(); bytes memory tempBytes; assembly ("memory-safe") { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address addr) { unchecked { if (_bytes.length < _start + 20) revert BytesLibToAddressOutOfBounds(); assembly ("memory-safe") { addr := and(0xffffffffffffffffffffffffffffffffffffffff, mload(add(add(_bytes, 20), _start))) } } } function toBool(bytes memory _bytes, uint256 _start) internal pure returns (bool) { unchecked { if (_bytes.length < _start + 1) revert BytesLibToBoolOutOfBounds(); uint8 tempUint; assembly ("memory-safe") { tempUint := mload(add(add(_bytes, 1), _start)) } return tempUint == 1; } } function toAddressAddressBoolUint128Uint128( bytes memory _bytes ) internal pure returns (address addr1, address addr2, bool bool_, uint128 amount1, uint128 amount2) { if (_bytes.length != 73) revert BytesLibInvalidLength(_bytes.length, 73); uint8 temp; assembly ("memory-safe") { addr1 := and(0xffffffffffffffffffffffffffffffffffffffff, mload(add(_bytes, 20))) addr2 := and(0xffffffffffffffffffffffffffffffffffffffff, mload(add(_bytes, 40))) temp := mload(add(_bytes, 41)) amount1 := and(0xffffffffffffffffffffffffffffffff, mload(add(_bytes, 57))) amount2 := and(0xffffffffffffffffffffffffffffffff, mload(add(_bytes, 73))) } bool_ = temp == 1; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; // adapted from https://github.com/latticexyz/mud/blob/main/packages/store/src/Slice.sol import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; import {SafeCast as Cast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import {BytesLib} from "./BytesLib.sol"; library PackLib { using Cast for uint256; using BytesLib for bytes; function unpackExactInputSingleArgsAmounts( bytes memory argsPacked ) internal pure returns (address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountIn, uint256 amountOutMinimum) { address pool_; (recipient, pool_, tokenAIn, amountIn, amountOutMinimum) = argsPacked.toAddressAddressBoolUint128Uint128(); pool = IMaverickV2Pool(pool_); } function unpackAddLiquidityArgs( bytes memory argsPacked ) internal pure returns (IMaverickV2Pool.AddLiquidityParams memory args) { args.kind = uint8(argsPacked[0]); args.ticks = unpackInt32Array(argsPacked.slice(1, argsPacked.length - 1)); uint256 startByte = args.ticks.length * 4 + 2; args.amounts = unpackUint128Array(argsPacked.slice(startByte, argsPacked.length - startByte)); } function packAddLiquidityArgs( IMaverickV2Pool.AddLiquidityParams memory args ) internal pure returns (bytes memory argsPacked) { argsPacked = abi.encodePacked(args.kind); argsPacked = bytes.concat(argsPacked, packArray(args.ticks)); argsPacked = bytes.concat(argsPacked, packArray(args.amounts)); } function packAddLiquidityArgsToArray( IMaverickV2Pool.AddLiquidityParams memory args ) internal pure returns (bytes[] memory argsPacked) { argsPacked = new bytes[](1); argsPacked[0] = packAddLiquidityArgs(args); } function packAddLiquidityArgsArray( IMaverickV2Pool.AddLiquidityParams[] memory args ) internal pure returns (bytes[] memory argsPacked) { argsPacked = new bytes[](args.length); for (uint256 k; k < args.length; k++) { argsPacked[k] = packAddLiquidityArgs(args[k]); } } function unpackInt32Array(bytes memory input) internal pure returns (int32[] memory array) { uint256[] memory output = _unpackArray(input, 4); assembly ("memory-safe") { array := output } } function unpackUint128Array(bytes memory input) internal pure returns (uint128[] memory array) { uint256[] memory output = _unpackArray(input, 16); assembly ("memory-safe") { array := output } } function unpackUint88Array(bytes memory input) internal pure returns (uint88[] memory array) { uint256[] memory output = _unpackArray(input, 11); assembly ("memory-safe") { array := output } } function packArray(int32[] memory array) internal pure returns (bytes memory output) { uint256[] memory input; assembly ("memory-safe") { input := array } output = _packArray(input, 4); } function packArray(uint128[] memory array) internal pure returns (bytes memory output) { uint256[] memory input; assembly ("memory-safe") { input := array } output = _packArray(input, 16); } function packArray(uint88[] memory array) internal pure returns (bytes memory output) { uint256[] memory input; assembly ("memory-safe") { input := array } output = _packArray(input, 11); } /* * @notice [length, array[0], array[1],..., array[length-1]]. length is 1 bytes. * @dev Unpacked signed array elements will contain "dirty bits". That is, * this function does not 0xf pad signed return elements. */ function _unpackArray(bytes memory input, uint256 elementBytes) internal pure returns (uint256[] memory array) { uint256 packedPointer; uint256 arrayLength; assembly ("memory-safe") { // read from input pointer + 32 bytes // pad 1-byte length value to fill 32 bytes (248 pad bits) arrayLength := shr(248, mload(add(input, 0x20))) packedPointer := add(input, 0x21) } uint256 padRight = 256 - 8 * elementBytes; assembly ("memory-safe") { // Allocate a word for each element, and a word for the array's length let allocateBytes := add(mul(arrayLength, 32), 0x20) // Allocate memory and update the free memory pointer array := mload(0x40) mstore(0x40, add(array, allocateBytes)) // Store array length mstore(array, arrayLength) for { let i := 0 let arrayCursor := add(array, 0x20) // skip array length let packedCursor := packedPointer } lt(i, arrayLength) { // Loop until we reach the end of the array i := add(i, 1) arrayCursor := add(arrayCursor, 0x20) // increment array pointer by one word packedCursor := add(packedCursor, elementBytes) // increment packed pointer by one element size } { mstore(arrayCursor, shr(padRight, mload(packedCursor))) // unpack one array element } } } /* * @dev [length, array[0], array[1],..., array[length-1]]. length is 1 bytes. */ function _packArray(uint256[] memory array, uint256 elementBytes) internal pure returns (bytes memory output) { // cast to check size fits in 8 bits uint8 arrayLength = array.length.toUint8(); uint256 packedLength = arrayLength * elementBytes + 1; output = new bytes(packedLength); uint256 padLeft = 256 - 8 * elementBytes; assembly ("memory-safe") { // Store array length mstore(add(output, 0x20), shl(248, arrayLength)) for { let i := 0 let arrayCursor := add(array, 0x20) // skip array length let packedCursor := add(output, 0x21) // skip length } lt(i, arrayLength) { // Loop until we reach the end of the array i := add(i, 1) arrayCursor := add(arrayCursor, 0x20) // increment array pointer by one word packedCursor := add(packedCursor, elementBytes) // increment packed pointer by one element size } { mstore(packedCursor, shl(padLeft, mload(arrayCursor))) // pack one array element } } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; import {BytesLib} from "./BytesLib.sol"; /** * @notice Path is [pool_addr, tokenAIn, pool_addr, tokenAIn ...], alternating 20 * bytes and then one byte for the tokenAIn bool. */ library Path { using BytesLib for bytes; /** * @notice The length of the bytes encoded address. */ uint256 private constant ADDR_SIZE = 20; /** * @notice The length of the bytes encoded bool. */ uint256 private constant BOOL_SIZE = 1; /** * @notice The offset of a single token address and pool address. */ uint256 private constant NEXT_OFFSET = ADDR_SIZE + BOOL_SIZE; /** * @notice Returns true iff the path contains two or more pools. * @param path The encoded swap path. * @return True if path contains two or more pools, otherwise false. */ function hasMultiplePools(bytes memory path) internal pure returns (bool) { return path.length > NEXT_OFFSET; } /** * @notice Decodes the first pool in path. * @param path The bytes encoded swap path. */ function decodeFirstPool(bytes memory path) internal pure returns (IMaverickV2Pool pool, bool tokenAIn) { pool = IMaverickV2Pool(path.toAddress(0)); tokenAIn = path.toBool(ADDR_SIZE); } function decodeNextPoolAddress(bytes memory path) internal pure returns (address pool) { pool = path.toAddress(NEXT_OFFSET); } /** * @notice Skips a token + pool element from the buffer and returns the * remainder. * @param path The swap path. * @return The remaining token + pool elements in the path. */ function skipToken(bytes memory path) internal pure returns (bytes memory) { return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {SafeCast as Cast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; import {Math} from "@maverick/v2-common/contracts/libraries/Math.sol"; import {PoolLib} from "@maverick/v2-common/contracts/libraries/PoolLib.sol"; import {TickMath} from "@maverick/v2-common/contracts/libraries/TickMath.sol"; library PoolInspection { using Cast for uint256; /** * @dev Calculates the square root price of a given Maverick V2 pool. * @param pool The Maverick V2 pool to inspect. * @return sqrtPrice The square root price of the pool. */ function poolSqrtPrice(IMaverickV2Pool pool) internal view returns (uint256 sqrtPrice) { int32 activeTick = pool.getState().activeTick; IMaverickV2Pool.TickState memory tickState = pool.getTick(activeTick); (uint256 sqrtLowerTickPrice, uint256 sqrtUpperTickPrice) = TickMath.tickSqrtPrices( pool.tickSpacing(), activeTick ); (sqrtPrice, ) = TickMath.getTickSqrtPriceAndL( tickState.reserveA, tickState.reserveB, sqrtLowerTickPrice, sqrtUpperTickPrice ); } /** * @dev Retrieves the reserves of a user's subaccount for a specific bin. */ function userSubaccountBinReserves( IMaverickV2Pool pool, address user, uint256 subaccount, uint32 binId ) internal view returns (uint256 amountA, uint256 amountB, int32 tick, uint256 liquidity) { IMaverickV2Pool.BinState memory bin = pool.getBin(binId); uint256 userBinLpBalance = pool.balanceOf(user, subaccount, binId); while (bin.mergeId != 0) { userBinLpBalance = bin.totalSupply == 0 ? 0 : Math.mulDivFloor(userBinLpBalance, bin.mergeBinBalance, bin.totalSupply); bin = pool.getBin(bin.mergeId); } tick = bin.tick; IMaverickV2Pool.TickState memory tickState = pool.getTick(tick); uint256 activeBinDeltaLpBalance = Math.min(userBinLpBalance, bin.totalSupply); uint128 deltaTickBalance = Math .mulDivDown(activeBinDeltaLpBalance, bin.tickBalance, bin.totalSupply) .toUint128(); deltaTickBalance = Math.min128(deltaTickBalance, tickState.totalSupply); (amountA, amountB) = PoolLib.binReserves( deltaTickBalance, tickState.reserveA, tickState.reserveB, tickState.totalSupply ); { (uint256 sqrtLowerTickPrice, uint256 sqrtUpperTickPrice) = TickMath.tickSqrtPrices( pool.tickSpacing(), tick ); liquidity = TickMath.getTickL(amountA, amountB, sqrtLowerTickPrice, sqrtUpperTickPrice); } } /** * @dev Retrieves the reserves of a token for all bins associated with it. * Bin reserve amounts are in pool D18 scale units. */ function subaccountPositionInformation( IMaverickV2Pool pool, address user, uint256 subaccount, uint32[] memory binIds ) internal view returns ( uint256 amountA, uint256 amountB, uint256[] memory binAAmounts, uint256[] memory binBAmounts, int32[] memory ticks, uint256[] memory liquidities ) { binAAmounts = new uint256[](binIds.length); binBAmounts = new uint256[](binIds.length); ticks = new int32[](binIds.length); liquidities = new uint256[](binIds.length); for (uint256 i; i < binIds.length; i++) { (binAAmounts[i], binBAmounts[i], ticks[i], liquidities[i]) = userSubaccountBinReserves( pool, user, subaccount, binIds[i] ); amountA += binAAmounts[i]; amountB += binBAmounts[i]; } { uint256 tokenAScale = pool.tokenAScale(); uint256 tokenBScale = pool.tokenBScale(); amountA = Math.ammScaleToTokenScale(amountA, tokenAScale, false); amountB = Math.ammScaleToTokenScale(amountB, tokenBScale, false); } } function binLpBalances( IMaverickV2Pool pool, uint32[] memory binIds, uint256 subaccount ) internal view returns (uint128[] memory amounts) { amounts = new uint128[](binIds.length); for (uint256 i = 0; i < binIds.length; i++) { amounts[i] = pool.balanceOf(address(this), subaccount, binIds[i]); } } function lpBalanceForTargetReserveAmounts( IMaverickV2Pool pool, uint32 binId, uint256 amountA, uint256 amountB, uint256 scaleA, uint256 scaleB ) internal view returns (IMaverickV2Pool.AddLiquidityParams memory addParams) { amountA = Math.tokenScaleToAmmScale(amountA, scaleA); amountB = Math.tokenScaleToAmmScale(amountB, scaleB); IMaverickV2Pool.BinState memory bin = pool.getBin(binId); uint128[] memory amounts = new uint128[](1); IMaverickV2Pool.TickState memory tickState = pool.getTick(bin.tick); uint256 numerator = Math.max(1, uint256(tickState.totalSupply)) * Math.max(1, uint256(bin.totalSupply)); if (amountA != 0) { uint256 denominator = Math.max(1, uint256(bin.tickBalance)) * uint256(tickState.reserveA); amounts[0] = Math.mulDivFloor(amountA, numerator, denominator).toUint128(); } if (amountB != 0) { uint256 denominator = Math.max(1, uint256(bin.tickBalance)) * uint256(tickState.reserveB); if (amountA != 0) { amounts[0] = Math.min128(amounts[0], Math.mulDivFloor(amountB, numerator, denominator).toUint128()); } else { amounts[0] = Math.mulDivFloor(amountB, numerator, denominator).toUint128(); } } { int32[] memory ticks = new int32[](1); ticks[0] = bin.tick; addParams = IMaverickV2Pool.AddLiquidityParams({kind: bin.kind, ticks: ticks, amounts: amounts}); } } function maxRemoveParams( IMaverickV2Pool pool, uint32 binId, address user, uint256 subaccount ) internal view returns (IMaverickV2Pool.RemoveLiquidityParams memory params) { uint32[] memory binIds = new uint32[](1); uint128[] memory amounts = new uint128[](1); binIds[0] = binId; amounts[0] = pool.balanceOf(user, subaccount, binId); params = IMaverickV2Pool.RemoveLiquidityParams({binIds: binIds, amounts: amounts}); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IPayableMulticall} from "@maverick/v2-common/contracts/base/IPayableMulticall.sol"; import {IState} from "./IState.sol"; interface IPayment is IPayableMulticall, IState { error PaymentSenderNotWETH9(); error PaymentInsufficientBalance(address token, uint256 amountMinimum, uint256 contractBalance); receive() external payable; /** * @notice Unwrap WETH9 tokens into ETH and send that balance to recipient. * If less than amountMinimum WETH is avialble, then revert. */ function unwrapWETH9(uint256 amountMinimum, address recipient) external payable; /** * @notice Transfers specified token amount to recipient */ function sweepTokenAmount(IERC20 token, uint256 amount, address recipient) external payable; /** * @notice Sweep entire ERC20 token balance on this contract to recipient. * If less than amountMinimum balance is avialble, then revert. */ function sweepToken(IERC20 token, uint256 amountMinimum, address recipient) external payable; /** * @notice Send any ETH on this contract to msg.sender. */ function refundETH() external payable; /** * @notice For tokenA and tokenB, sweep all of the * non-WETH tokens to msg.sender. Any WETH balance is unwrapped to ETH and * then all the ETH on this contract is sent to msg.sender. */ function unwrapAndSweep( IERC20 tokenA, IERC20 tokenB, uint256 tokenAAmountMin, uint256 tokenBAmountMin ) external payable; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IWETH9} from "./IWETH9.sol"; import {IMaverickV2Factory} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Factory.sol"; interface IState { function weth() external view returns (IWETH9 _weth); function factory() external view returns (IMaverickV2Factory _factory); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH9 is IERC20 { event Deposit(address indexed dst, uint256 wad); event Withdrawal(address indexed src, uint256 wad); function deposit() external payable; function withdraw(uint256) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; import {TransferLib} from "@maverick/v2-common/contracts/libraries/TransferLib.sol"; import {PayableMulticall} from "@maverick/v2-common/contracts/base/PayableMulticall.sol"; import {IWETH9} from "./IWETH9.sol"; import {State} from "./State.sol"; import {IPayment} from "./IPayment.sol"; /** * @notice Payment helper function that lets user sweep ERC20 tokens off the * router and liquidity manager. Also provides mechanism to wrap and unwrap * ETH/WETH so that it can be used in the Maverick pools. */ abstract contract Payment is State, PayableMulticall, IPayment { receive() external payable { if (IWETH9(msg.sender) != weth()) revert PaymentSenderNotWETH9(); } /// @inheritdoc IPayment function unwrapWETH9(uint256 amountMinimum, address recipient) public payable { uint256 balanceWETH9 = weth().balanceOf(address(this)); if (balanceWETH9 < amountMinimum) revert PaymentInsufficientBalance(address(weth()), amountMinimum, balanceWETH9); if (balanceWETH9 > 0) { weth().withdraw(balanceWETH9); Address.sendValue(payable(recipient), balanceWETH9); } } /// @inheritdoc IPayment function sweepToken(IERC20 token, uint256 amountMinimum, address recipient) public payable { uint256 balanceToken = token.balanceOf(address(this)); if (balanceToken < amountMinimum) revert PaymentInsufficientBalance(address(token), amountMinimum, balanceToken); if (balanceToken > 0) { TransferLib.transfer(token, recipient, balanceToken); } } /// @inheritdoc IPayment function sweepTokenAmount(IERC20 token, uint256 amount, address recipient) public payable { TransferLib.transfer(token, recipient, amount); } /// @inheritdoc IPayment function unwrapAndSweep( IERC20 tokenA, IERC20 tokenB, uint256 tokenAAmountMin, uint256 tokenBAmountMin ) public payable { if (address(tokenA) == address(weth())) { unwrapWETH9(tokenAAmountMin, msg.sender); refundETH(); sweepToken(tokenB, tokenBAmountMin, msg.sender); } else if (address(tokenB) == address(weth())) { sweepToken(tokenA, tokenAAmountMin, msg.sender); unwrapWETH9(tokenBAmountMin, msg.sender); refundETH(); } else { sweepToken(tokenA, tokenAAmountMin, msg.sender); sweepToken(tokenB, tokenBAmountMin, msg.sender); } } /// @inheritdoc IPayment function refundETH() public payable { if (address(this).balance > 0) Address.sendValue(payable(msg.sender), address(this).balance); } /** * @notice Internal function to pay tokens or eth. * @param token ERC20 token to pay. * @param payer Address of the payer. * @param recipient Address of the recipient. * @param value Amount of tokens to pay. */ function pay(IERC20 token, address payer, address recipient, uint256 value) internal { if (IWETH9(address(token)) == weth() && address(this).balance >= value) { weth().deposit{value: value}(); weth().transfer(recipient, value); } else if (payer == address(this)) { TransferLib.transfer(token, recipient, value); } else { TransferLib.transferFrom(token, payer, recipient, value); } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IMaverickV2Factory} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Factory.sol"; import {IWETH9} from "./IWETH9.sol"; import {IState} from "./IState.sol"; abstract contract State is IState { IWETH9 private immutable _weth; IMaverickV2Factory private immutable _factory; constructor(IMaverickV2Factory __factory, IWETH9 __weth) { _factory = __factory; _weth = __weth; } function weth() public view returns (IWETH9 weth_) { weth_ = _weth; } function factory() public view returns (IMaverickV2Factory factory_) { factory_ = _factory; } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; import {ICallbackOperations} from "./ICallbackOperations.sol"; import {Path} from "../libraries/Path.sol"; import {ExactOutputSlim} from "./ExactOutputSlim.sol"; abstract contract CallbackOperations is ExactOutputSlim, ICallbackOperations { using Path for bytes; struct CallbackData { bytes path; address payer; } uint256 private __amountIn = type(uint256).max; /// @inheritdoc ICallbackOperations function exactOutputSingle( address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountOut, uint256 amountInMaximum ) public payable returns (uint256 amountIn, uint256 amountOut_) { int32 tickLimit = tokenAIn ? type(int32).max : type(int32).min; (amountIn, amountOut_) = _exactOutputSingleWithTickCheck(pool, recipient, amountOut, tokenAIn, tickLimit); if (amountIn > amountInMaximum) revert RouterTooMuchRequested(amountInMaximum, amountIn); } /// @inheritdoc ICallbackOperations function outputSingleWithTickLimit( address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountOut, int32 tickLimit, uint256 amountInMaximum, uint256 amountOutMinimum ) public payable returns (uint256 amountIn_, uint256 amountOut_) { (amountIn_, amountOut_) = _exactOutputSingleWithTickCheck(pool, recipient, amountOut, tokenAIn, tickLimit); if (amountIn_ > amountInMaximum) revert RouterTooMuchRequested(amountInMaximum, amountIn_); if (amountOut_ < amountOutMinimum) revert RouterTooLittleReceived(amountOutMinimum, amountOut_); } /// @inheritdoc ICallbackOperations function exactOutputMultiHop( address recipient, bytes memory path, uint256 amountOut, uint256 amountInMaximum ) public payable returns (uint256 amountIn) { // recursively swap through the hops starting with the ouput pool. // inside of the swap callback, this contract will call the next pool // in the path until it gets to the input pool of the path. _exactOutputInternal(amountOut, recipient, CallbackData({path: path, payer: msg.sender})); amountIn = __amountIn; if (amountIn > amountInMaximum) revert RouterTooMuchRequested(amountInMaximum, amountIn); __amountIn = type(uint256).max; } /// @inheritdoc ICallbackOperations function inputSingleWithTickLimit( address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountIn, int32 tickLimit, uint256 amountOutMinimum ) public payable returns (uint256 amountIn_, uint256 amountOut) { // swap IMaverickV2Pool.SwapParams memory swapParams = IMaverickV2Pool.SwapParams({ amount: amountIn, tokenAIn: tokenAIn, exactOutput: false, tickLimit: tickLimit }); (amountIn_, amountOut) = _swap(pool, recipient, swapParams, abi.encode(msg.sender)); if (amountOut < amountOutMinimum) revert RouterTooLittleReceived(amountOutMinimum, amountOut); } function _exactOutputInternal( uint256 amountOut, address recipient, CallbackData memory data ) internal returns (uint256 amountIn) { if (recipient == address(0)) recipient = address(this); (IMaverickV2Pool pool, bool tokenAIn) = data.path.decodeFirstPool(); int32 tickLimit = tokenAIn ? type(int32).max : type(int32).min; IMaverickV2Pool.SwapParams memory swapParams = IMaverickV2Pool.SwapParams({ amount: amountOut, tokenAIn: tokenAIn, exactOutput: true, tickLimit: tickLimit }); uint256 amountOutReceived; (amountIn, amountOutReceived) = _swap(pool, recipient, swapParams, abi.encode(data)); } function maverickV2SwapCallback( IERC20 tokenIn, uint256 amountToPay, uint256, bytes calldata _data ) external override { // only used for either single-hop exactinput calls with a tick limit, // or exactouput calls. if the path has more than one pool, then this // is an exactouput multihop swap. if (amountToPay == 0) revert RouterZeroSwap(); if (!factory().isFactoryPool(IMaverickV2Pool(msg.sender))) revert RouterNotFactoryPool(); if (_data.length == 32) { // exact in address payer = abi.decode(_data, (address)); pay(tokenIn, payer, msg.sender, amountToPay); } else { // exact out CallbackData memory data = abi.decode(_data, (CallbackData)); if (data.path.hasMultiplePools()) { data.path = data.path.skipToken(); _exactOutputInternal(amountToPay, msg.sender, data); } else { // must be at first/input pool __amountIn = amountToPay; pay(tokenIn, data.payer, msg.sender, amountToPay); } } } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; import {Payment} from "../paymentbase/Payment.sol"; import {IExactOutputSlim} from "./IExactOutputSlim.sol"; import {Swap} from "./Swap.sol"; abstract contract ExactOutputSlim is Payment, Swap, IExactOutputSlim { /** * @dev Callback function called by Maverick V2 pools when swapping tokens. * @param tokenIn The input token. * @param amountToPay The amount to pay. * @param data Additional data. */ function maverickV2SwapCallback( IERC20 tokenIn, uint256 amountToPay, uint256, bytes calldata data ) external virtual { if (!factory().isFactoryPool(IMaverickV2Pool(msg.sender))) revert RouterNotFactoryPool(); address payer = abi.decode(data, (address)); if (amountToPay != 0) pay(tokenIn, payer, msg.sender, amountToPay); } /** * @dev Perform a swap with an exact output amount. * @param recipient The recipient of the swapped tokens. * @param pool The MaverickV2 pool to use for the swap. * @param tokenAIn Whether token A is the input token. * @param amountOut The exact output amount. * @param tickLimit The tick limit for the swap. * @return amountIn The input amount required to achieve the exact output. * @return amountOut_ The actual output amount received from the swap. */ function exactOutputSingleMinimal( address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountOut, int32 tickLimit ) public payable returns (uint256 amountIn, uint256 amountOut_) { (amountIn, amountOut_) = _exactOutputSingleWithTickCheck(pool, recipient, amountOut, tokenAIn, tickLimit); } /** * @dev Perform an exact output single swap with tick limit validation. * @param pool The MaverickV2 pool to use for the swap. * @param recipient The recipient of the swapped tokens. * @param amountOut The exact output amount. * @param tokenAIn Whether token A is the input token. * @param tickLimit The tick limit for the swap. * @return amountIn The input amount required to achieve the exact output. * @return _amountOut The actual output amount received from the swap. */ function _exactOutputSingleWithTickCheck( IMaverickV2Pool pool, address recipient, uint256 amountOut, bool tokenAIn, int32 tickLimit ) internal returns (uint256 amountIn, uint256 _amountOut) { IMaverickV2Pool.SwapParams memory swapParams = IMaverickV2Pool.SwapParams({ amount: amountOut, tokenAIn: tokenAIn, exactOutput: true, tickLimit: tickLimit }); (amountIn, _amountOut) = _swap( pool, (recipient == address(0)) ? address(this) : recipient, swapParams, abi.encode(msg.sender) ); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; import {IExactOutputSlim} from "./IExactOutputSlim.sol"; interface ICallbackOperations is IExactOutputSlim { /** * @notice Perform an exact output single swap. * @param recipient The address of the recipient. * @param pool The Maverick V2 pool to swap with. * @param tokenAIn A boolean indicating if token A is the input. * @param amountOut The amount of output tokens desired. * @param amountInMaximum The maximum amount of input tokens allowed. * @return amountIn The amount of input tokens used for the swap. * @return amountOut_ The actual amount of output tokens received. */ function exactOutputSingle( address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountOut, uint256 amountInMaximum ) external payable returns (uint256 amountIn, uint256 amountOut_); /** * @notice Perform an output-specified single swap with tick limit check. * @param recipient The address of the recipient. * @param pool The Maverick V2 pool to swap with. * @param tokenAIn A boolean indicating if token A is the input. * @param amountOut The amount of output tokens desired. * @param tickLimit The tick limit for the swap. * @param amountInMaximum The maximum amount of input tokens allowed. * @param amountOutMinimum The minimum amount of output tokens expected. * @return amountIn_ The actual amount of input tokens used for the swap. * @return amountOut_ The actual amount of output tokens received. This * amount can vary from the requested amountOut due to the tick limit. If * the pool swaps to the tick limit, it will stop filling the order and * return the amount out swapped up to the ticklimit to the user. */ function outputSingleWithTickLimit( address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountOut, int32 tickLimit, uint256 amountInMaximum, uint256 amountOutMinimum ) external payable returns (uint256 amountIn_, uint256 amountOut_); /** * @notice Perform an exact output multihop swap. * @param recipient The recipient address. * @param path The swap path as encoded bytes. * @param amountOut The exact output amount. * @param amountInMaximum The maximum input amount allowed. * @return amountIn The input amount for the swap. */ function exactOutputMultiHop( address recipient, bytes memory path, uint256 amountOut, uint256 amountInMaximum ) external payable returns (uint256 amountIn); /** * @notice Perform an input-specified single swap with tick limit check. * @param recipient The address of the recipient. * @param pool The Maverick V2 pool to swap with. * @param tokenAIn A boolean indicating if token A is the input. * @param amountIn The amount of input tokens. * @param tickLimit The tick limit for the swap. * @param amountOutMinimum The minimum amount of output tokens expected. * @return amountIn_ The actual input amount used for the swap. This may * differ from the amount the caller specified if the pool reaches the tick * limit. In that case, the pool will consume the input swap amount up to * the tick limit and return the resulting output amount to the user. * @return amountOut The amount of output tokens received. */ function inputSingleWithTickLimit( address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountIn, int32 tickLimit, uint256 amountOutMinimum ) external payable returns (uint256 amountIn_, uint256 amountOut); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; import {IRouterErrors} from "./IRouterErrors.sol"; interface IExactOutputSlim is IRouterErrors { function exactOutputSingleMinimal( address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountOut, int32 tickLimit ) external payable returns (uint256 amountIn, uint256 amountOut_); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; import {IRouterErrors} from "./IRouterErrors.sol"; interface IPushOperations is IRouterErrors { /** * @notice Perform an exact input single swap with compressed input values. */ function exactInputSinglePackedArgs(bytes memory argsPacked) external payable returns (uint256 amountOut); /** * @notice Perform an exact input single swap without tick limit check. * @param recipient The address of the recipient. * @param pool The Maverick V2 pool to swap with. * @param tokenAIn True is tokenA is the input token. False is tokenB is * the input token. * @param amountIn The amount of input tokens. * @param amountOutMinimum The minimum amount of output tokens expected. */ function exactInputSingle( address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountIn, uint256 amountOutMinimum ) external payable returns (uint256 amountOut); /** * @notice Perform an exact input multi-hop swap. * @param recipient The address of the recipient. * @param path The path of tokens to swap. * @param amountIn The amount of input tokens. * @param amountOutMinimum The minimum amount of output tokens expected. */ function exactInputMultiHop( address recipient, bytes memory path, uint256 amountIn, uint256 amountOutMinimum ) external payable returns (uint256 amountOut); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; interface IRouterErrors { error RouterZeroSwap(); error RouterNotFactoryPool(); error RouterTooLittleReceived(uint256 amountOutMinimum, uint256 amountOut); error RouterTooMuchRequested(uint256 amountInMaximum, uint256 amountIn); }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; import {PackLib} from "../libraries/PackLib.sol"; import {Payment} from "../paymentbase/Payment.sol"; import {Path} from "../libraries/Path.sol"; import {IPushOperations} from "./IPushOperations.sol"; import {Swap} from "./Swap.sol"; /** * @notice Exactinput router operations that can be performed by pushing assets * to the pool to swap. */ abstract contract PushOperations is Payment, Swap, IPushOperations { using Path for bytes; /// @inheritdoc IPushOperations function exactInputSinglePackedArgs(bytes memory argsPacked) public payable returns (uint256 amountOut) { (address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountIn, uint256 amountOutMinimum) = PackLib .unpackExactInputSingleArgsAmounts(argsPacked); return exactInputSingle(recipient, pool, tokenAIn, amountIn, amountOutMinimum); } /// @inheritdoc IPushOperations function exactInputSingle( address recipient, IMaverickV2Pool pool, bool tokenAIn, uint256 amountIn, uint256 amountOutMinimum ) public payable returns (uint256 amountOut) { // pay pool pay(tokenAIn ? pool.tokenA() : pool.tokenB(), msg.sender, address(pool), amountIn); // swap IMaverickV2Pool.SwapParams memory swapParams = IMaverickV2Pool.SwapParams({ amount: amountIn, tokenAIn: tokenAIn, exactOutput: false, tickLimit: tokenAIn ? type(int32).max : type(int32).min }); (, amountOut) = _swap(pool, recipient, swapParams, bytes("")); // check slippage if (amountOut < amountOutMinimum) revert RouterTooLittleReceived(amountOutMinimum, amountOut); } /// @inheritdoc IPushOperations function exactInputMultiHop( address recipient, bytes memory path, uint256 amountIn, uint256 amountOutMinimum ) public payable returns (uint256 amountOut) { (IMaverickV2Pool pool, bool tokenAIn) = path.decodeFirstPool(); // pay first pool pay(tokenAIn ? pool.tokenA() : pool.tokenB(), msg.sender, address(pool), amountIn); amountOut = amountIn; while (true) { // if we have more pools, pay next pool, if not, pay recipient bool stillMultiPoolSwap = path.hasMultiplePools(); address nextRecipient = stillMultiPoolSwap ? path.decodeNextPoolAddress() : recipient; // do swap and send proceeds to nextRecipient IMaverickV2Pool.SwapParams memory swapParams = IMaverickV2Pool.SwapParams({ amount: amountOut, tokenAIn: tokenAIn, exactOutput: false, tickLimit: tokenAIn ? type(int32).max : type(int32).min }); (, amountOut) = _swap(pool, nextRecipient, swapParams, bytes("")); // if there is more path, loop, if not, break if (stillMultiPoolSwap) { path = path.skipToken(); (pool, tokenAIn) = path.decodeFirstPool(); } else { break; } } if (amountOut < amountOutMinimum) revert RouterTooLittleReceived(amountOutMinimum, amountOut); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity ^0.8.25; import {IMaverickV2Pool} from "@maverick/v2-common/contracts/interfaces/IMaverickV2Pool.sol"; /** * @notice Base contract support for swaps */ abstract contract Swap { /** * @notice Internal swap function. Override this function to add logic * before or after a swap. */ function _swap( IMaverickV2Pool pool, address recipient, IMaverickV2Pool.SwapParams memory params, bytes memory data ) internal virtual returns (uint256 amountIn, uint256 amountOut) { (amountIn, amountOut) = pool.swap(recipient, params, data); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } }
{ "optimizer": { "enabled": true, "runs": 5500 }, "viaIR": true, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IMaverickV2Factory","name":"_factory","type":"address"},{"internalType":"contract IWETH9","name":"_weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"uint256","name":"inputLength","type":"uint256"},{"internalType":"uint256","name":"expectedLength","type":"uint256"}],"name":"BytesLibInvalidLength","type":"error"},{"inputs":[],"name":"BytesLibSliceOutOfBounds","type":"error"},{"inputs":[],"name":"BytesLibSliceOverflow","type":"error"},{"inputs":[],"name":"BytesLibToAddressOutOfBounds","type":"error"},{"inputs":[],"name":"BytesLibToBoolOutOfBounds","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"MathOverflowedMulDiv","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"uint256","name":"contractBalance","type":"uint256"}],"name":"PaymentInsufficientBalance","type":"error"},{"inputs":[],"name":"PaymentSenderNotWETH9","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"}],"name":"PositionDeadlinePassed","type":"error"},{"inputs":[{"internalType":"uint256","name":"sqrtPrice","type":"uint256"},{"internalType":"uint256","name":"minSqrtPrice","type":"uint256"},{"internalType":"uint256","name":"maxSqrtPrice","type":"uint256"}],"name":"PositionExceededPriceBounds","type":"error"},{"inputs":[],"name":"RouterNotFactoryPool","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"RouterTooLittleReceived","type":"error"},{"inputs":[{"internalType":"uint256","name":"amountInMaximum","type":"uint256"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"RouterTooMuchRequested","type":"error"},{"inputs":[],"name":"RouterZeroSwap","type":"error"},{"inputs":[{"internalType":"int256","name":"tick","type":"int256"}],"name":"TickMaxExceeded","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferFailed","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferFromFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"checkDeadline","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IMaverickV2Pool","name":"pool","type":"address"},{"internalType":"uint256","name":"minSqrtPrice","type":"uint256"},{"internalType":"uint256","name":"maxSqrtPrice","type":"uint256"}],"name":"checkSqrtPrice","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"}],"name":"exactInputMultiHop","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"contract IMaverickV2Pool","name":"pool","type":"address"},{"internalType":"bool","name":"tokenAIn","type":"bool"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"}],"name":"exactInputSingle","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"argsPacked","type":"bytes"}],"name":"exactInputSinglePackedArgs","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"bytes","name":"path","type":"bytes"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"name":"exactOutputMultiHop","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"contract IMaverickV2Pool","name":"pool","type":"address"},{"internalType":"bool","name":"tokenAIn","type":"bool"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"}],"name":"exactOutputSingle","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"contract IMaverickV2Pool","name":"pool","type":"address"},{"internalType":"bool","name":"tokenAIn","type":"bool"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"int32","name":"tickLimit","type":"int32"}],"name":"exactOutputSingleMinimal","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IMaverickV2Factory","name":"factory_","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"contract IMaverickV2Pool","name":"pool","type":"address"},{"internalType":"bool","name":"tokenAIn","type":"bool"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"int32","name":"tickLimit","type":"int32"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"}],"name":"inputSingleWithTickLimit","outputs":[{"internalType":"uint256","name":"amountIn_","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountToPay","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"maverickV2SwapCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"contract IMaverickV2Pool","name":"pool","type":"address"},{"internalType":"bool","name":"tokenAIn","type":"bool"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"int32","name":"tickLimit","type":"int32"},{"internalType":"uint256","name":"amountInMaximum","type":"uint256"},{"internalType":"uint256","name":"amountOutMinimum","type":"uint256"}],"name":"outputSingleWithTickLimit","outputs":[{"internalType":"uint256","name":"amountIn_","type":"uint256"},{"internalType":"uint256","name":"amountOut_","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"refundETH","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepToken","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"sweepTokenAmount","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenA","type":"address"},{"internalType":"contract IERC20","name":"tokenB","type":"address"},{"internalType":"uint256","name":"tokenAAmountMin","type":"uint256"},{"internalType":"uint256","name":"tokenBAmountMin","type":"uint256"}],"name":"unwrapAndSweep","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountMinimum","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"unwrapWETH9","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH9","name":"weth_","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60c03460a857601f6127c538819003918201601f19168301916001600160401b0383118484101760ad57808492604094855283398101031260a85780516001600160a01b0391828216820360a85760200151918216820360a85760a05260805260001960005560405161270190816100c48239608051818181602601528181610baf01528181610ec30152818161136e0152611998015260a05181818161019d01526109fb0152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe60406080815260049081361015610074575b361561001c57600080fd5b6001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016330361004e57005b517fc0f54629000000000000000000000000000000000000000000000000000000008152fd5b600060e08135811c90816312210e8a146110bc5781631841ad6d1461100157816319b871d314610f8157816328a5b3c914610ee75781633fc8cef314610ea357816349404b7c14610e83578163522ba7eb14610c3a578163670ca18114610b7f57816367ca7c911461095657816369b027ab146108dd578163a3b105ca146108be578163a4af5a7f146107fb578163a6990946146107aa578163ac9650d8146105f2578163b800a206146105a6578163b9e45300146101c557508063c45a01551461017d578063df2ab5bb1461016a5763f16d7904146101545750610011565b6101676101603661131c565b9091611e8d565b80f35b506101676101773661131c565b91611706565b5090346101c157816003193601126101c157602090516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b5080fd5b8484849260606003193601126105a2576101dd611200565b91602435916001600160a01b03604435941682517f1865c57d00000000000000000000000000000000000000000000000000000000815261012080828981865afa90811561048357899161048d575b5060a09150015160030b908351927f3256cfa900000000000000000000000000000000000000000000000000000000845282888501528084602481855afa938415610483579088949392918a946103a1575b50506020908551948580927fd0c93a7c0000000000000000000000000000000000000000000000000000000082525afa92831561039757889361035d575b506102db8360016102d08461030997611f96565b930160030b90611f96565b906fffffffffffffffffffffffffffffffff602081855116940151166103038383838761234c565b93612426565b908282108015610354575b61031c578580f35b6064955051937ffcb505c700000000000000000000000000000000000000000000000000000000855284015260248301526044820152fd5b50838211610314565b92506020833d60201161038f575b8161037860209383611167565b8101031261038b579151916102db6102bc565b8780fd5b3d915061036b565b84513d8a823e3d90fd5b919450809293503d831161047c575b6103ba8183611167565b8101918082840312610478578551926103d2846110d0565b6103db83611e51565b84526020916103ec60208501611e51565b60208601526103fc888501611e51565b8886015281607f8501121561047457875193610417856110d0565b84918101928311610470579060608c9897969594939201905b828210610449575050505060608201529160208a61027e565b839495969798509281929361045e8293611e7c565b81520191018b97969594939291610430565b8c80fd5b8b80fd5b8980fd5b503d6103b0565b85513d8b823e3d90fd5b80915082813d831161059b575b6104a48183611167565b8101031261059757845190810181811067ffffffffffffffff82111761056b5785526104cf82611e51565b81526104dd60208301611e51565b60208201526104ed858301611e6e565b858201526104fd60608301611e6e565b6060820152608082015164ffffffffff8116810361047857608082015260a08201518060030b81036104785760a082015261053a60c083016114ff565b60c082015261054a848301611e7c565b848201526101008092015160ff811681036104785760a0928201528961022c565b60248a60418b7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8880fd5b503d61049a565b8380fd5b505060a06003193601126105ef57506105e36105c0611200565b6105c8611216565b6105d061122c565b906105d9611281565b92606435916118a6565b82519182526020820152f35b80fd5b505082602091826003193601126105ef5781359167ffffffffffffffff908184116107a657366023850112156107a657830135908082116107a65760246005923660248260051b880101116107a2579261064b846116ab565b9561065889519788611167565b848752601f19610667866116ab565b0188875b8281106107925750505085917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbd82360301925b868110610720578a8a8a8a83519280840190808552835180925280868601968360051b870101940192955b8287106106d65785850386f35b909192938280610710837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08a6001960301865288516112dc565b96019201960195929190926106c9565b8481831b84010135848112156105975783018581013590878211610478576044019080360382136104785789808d610760600196956107769536916111a6565b80519101305af461076f6117f3565b9030611f2d565b610780828c6116c3565b5261078b818b6116c3565b500161069e565b60608a82018301528a910161066b565b8480fd5b8280fd5b82858560206003193601126107a6578135908142116107c7578380f35b6044935051917f3442e977000000000000000000000000000000000000000000000000000000008352820152426024820152fd5b50508260c06003193601126101c157610872610815611200565b61081d611216565b9061082661122c565b9061082f611281565b60a4359688519361083f856110d0565b6064358552151560208501528884015260030b60608301528651923360208501526020845261086d8461111b565b611b8e565b91909280831061088a57505082519182526020820152f35b916044928551927f84ae11480000000000000000000000000000000000000000000000000000000084528301526024820152fd5b6020846108d66108cd3661123b565b9392909261150c565b9051908152f35b8261090885876108ec36611291565b9592908551926108fb8461111b565b8352336020840152611da7565b508354928084116109225750506000196020935551908152f35b604493919251927f4956866a0000000000000000000000000000000000000000000000000000000084528301526024820152fd5b505091346107a65760806003193601126107a657610972611200565b602480359260643567ffffffffffffffff80821161038b573660238301121561038b57818301359681881161059757848301948884019281840192368411610474578915610b57576001600160a01b039a8b978d8351809a7f578eaca40000000000000000000000000000000000000000000000000000000082523384830152818860209d8e937f0000000000000000000000000000000000000000000000000000000000000000165afa918215610b4c5791610b13575b5015610aec57508703610a57575050505003126107a257359283168093036105a257610167923391611985565b91939490929996868287031261047457358381116104745782910180950312610478575197610a858961111b565b8284013591821161047857604492610a9f928501016111e2565b9182885201359283169283810361038b576015928701525111600014610add57505090610ad991610ad08251611c75565b82523390611da7565b5080f35b61016793508285553391611985565b82517f36294ff5000000000000000000000000000000000000000000000000000000008152fd5b90508981813d8311610b45575b610b2a8183611167565b81010312610b4157610b3b906114ff565b38610a2a565b8e80fd5b503d610b20565b8551903d90823e3d90fd5b8690517f63fa284a000000000000000000000000000000000000000000000000000000008152fd5b8260806003193601126105ef57610b94611200565b610b9c611216565b90604435606435916001600160a01b03807f000000000000000000000000000000000000000000000000000000000000000016908181841614600014610bfe5750505090610bef61016793923390611363565b610bf7611350565b3391611706565b8592951614600014610c295750610c2192610c1a913391611706565b3390611363565b610167611350565b919061016793610bf7913391611706565b838584610c4636611291565b9195929390610c5487611902565b909182908215610e105786517f0fc63d100000000000000000000000000000000000000000000000000000000081526020818b816001600160a01b0389165afa908115610e0657610cc19183918891610dd7575b509b94959b5b6001600160a01b03809d16903390611985565b82516015811194908515610dc9576029809110610da15790610d299392918501518c16905b8015610d9557637fffffff905b8a5193610cff856110d0565b845215156020840152878a84015260030b6060830152885192610d218461114b565b878452611b8e565b92159050610d4d57610d3a90611c75565b96610d4488611902565b91989192610cc1565b50935050808310610d62576020838351908152f35b90517f84ae1148000000000000000000000000000000000000000000000000000000008152928301526024820152604490fd5b637fffffff1990610cf3565b8a89517f41a6c181000000000000000000000000000000000000000000000000000000008152fd5b5090610d2992918990610ce6565b610df9915060203d602011610dff575b610df18183611167565b8101906114e0565b8d610ca8565b503d610de7565b88513d88823e3d90fd5b86517f5f64b55b0000000000000000000000000000000000000000000000000000000081526020818b816001600160a01b0389165afa908115610e0657610cc19183918891610e64575b509b94959b610cae565b610e7d915060203d602011610dff57610df18183611167565b8d610e5a565b8285856003193601126101c15761016790610e9c611216565b9035611363565b8284346101c157816003193601126101c157602090516001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000168152f35b849291506003193601126105ef5750610efe611200565b610f06611216565b91610f2c610f1261122c565b610f1a611281565b9060a4359560c43595606435916118a6565b929093808511610f4c575080831061088a57505082519182526020820152f35b82856044928851927f4956866a0000000000000000000000000000000000000000000000000000000084528301526024820152fd5b505082610fa8610f903661123b565b965091929091908215610ff557637fffffff936118a6565b919092808411610fc057505082519182526020820152f35b90836044928651927f4956866a0000000000000000000000000000000000000000000000000000000084528301526024820152fd5b637fffffff19936118a6565b505060206003193601126105ef5782359067ffffffffffffffff82116105ef575061102f90369084016111e2565b91825160498103611088576020836108d68660148101516001600160a01b0360288301518116602984015192600160ff603987015160496fffffffffffffffffffffffffffffffff98015188169716951614921661150c565b60449251917fd137d34b00000000000000000000000000000000000000000000000000000000835282015260496024820152fd5b82806003193601126105ef57610167611350565b6080810190811067ffffffffffffffff8211176110ec57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176110ec57604052565b67ffffffffffffffff81116110ec57604052565b6020810190811067ffffffffffffffff8211176110ec57604052565b90601f601f19910116810190811067ffffffffffffffff8211176110ec57604052565b67ffffffffffffffff81116110ec57601f01601f191660200190565b9291926111b28261118a565b916111c06040519384611167565b8294818452818301116111dd578281602093846000960137010152565b600080fd5b9080601f830112156111dd578160206111fd933591016111a6565b90565b600435906001600160a01b03821682036111dd57565b602435906001600160a01b03821682036111dd57565b6044359081151582036111dd57565b60031960a09101126111dd576001600160a01b039060043582811681036111dd579160243590811681036111dd579060443580151581036111dd57906064359060843590565b608435908160030b82036111dd57565b9060806003198301126111dd576004356001600160a01b03811681036111dd57916024359067ffffffffffffffff82116111dd576112d1916004016111e2565b906044359060643590565b919082519283825260005b848110611308575050601f19601f8460006020809697860101520116010190565b6020818301810151848301820152016112e7565b60031960609101126111dd576001600160a01b0360043581811681036111dd57916024359160443590811681036111dd5790565b4761135757565b6113614733611823565b565b6001600160a01b03807f00000000000000000000000000000000000000000000000000000000000000001692604051927f70a08231000000000000000000000000000000000000000000000000000000008452306004850152602084602481885afa938415611457576000946114ac575b508084106114635750826113e9575b50505050565b833b156111dd57600080946024604051809781937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528860048401525af19384156114575761143f94611448575b5016611823565b388080806113e3565b61145190611137565b38611438565b6040513d6000823e3d90fd5b6040517fd1cd07af0000000000000000000000000000000000000000000000000000000081526001600160a01b0386166004820152602481019190915260448101849052606490fd5b90936020823d6020116114d8575b816114c760209383611167565b810103126105ef57505192386113d4565b3d91506114ba565b908160209103126111dd57516001600160a01b03811681036111dd5790565b519081151582036111dd57565b93949391929091831561163657604051937f0fc63d100000000000000000000000000000000000000000000000000000000085526020856004816001600160a01b0388165afa8015611457578361157d916115c597600091611617575b505b6001600160a01b038716903390611985565b801561160b57637fffffff905b60405193611597856110d0565b8452151560208401526000604084015260030b6060830152604051926115bc8461114b565b60008452611b8e565b929050828181106115d4575050565b60449250604051917f84ae114800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b637fffffff199061158a565b611630915060203d602011610dff57610df18183611167565b38611569565b604051937f5f64b55b0000000000000000000000000000000000000000000000000000000085526020856004816001600160a01b0388165afa8015611457578361157d916115c59760009161168c575b5061156b565b6116a5915060203d602011610dff57610df18183611167565b38611686565b67ffffffffffffffff81116110ec5760051b60200190565b80518210156116d75760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b916001600160a01b03831691604051927f70a08231000000000000000000000000000000000000000000000000000000008452306004850152602084602481845afa938415611457576000946117bf575b508184106117745750508161176b57505050565b61136192611e8d565b6040517fd1cd07af0000000000000000000000000000000000000000000000000000000081526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b90936020823d6020116117eb575b816117da60209383611167565b810103126105ef5750519238611757565b3d91506117cd565b3d1561181e573d906118048261118a565b916118126040519384611167565b82523d6000602084013e565b606090565b8147106118765760008080936001600160a01b038294165af16118446117f3565b501561184c57565b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b60246040517fcd786059000000000000000000000000000000000000000000000000000000008152306004820152fd5b92936118f994604051936118b9856110d0565b8452151560208401526001604084015260030b60608301526001600160a01b0381166118fd5750305b604051923360208501526020845261086d8461111b565b9091565b6118e2565b90601482511061195b5760148201516001600160a01b0316916015815110611931576015015160ff1660011490565b60046040517f7c1be900000000000000000000000000000000000000000000000000000000008152fd5b60046040517f41a6c181000000000000000000000000000000000000000000000000000000008152fd5b9190916001600160a01b039081811690827f0000000000000000000000000000000000000000000000000000000000000000169485831480611b84575b15611ac357505050823b156111dd57604051917fd0e30db0000000000000000000000000000000000000000000000000000000008352600092838160048189895af18015611ab857611aa1575b50604490836020949560405197889586947fa9059cbb00000000000000000000000000000000000000000000000000000000865216600485015260248401525af18015611a9457611a5e575050565b6020823d602011611a8c575b81611a7760209383611167565b810103126105ef5750611a89906114ff565b50565b3d9150611a6a565b50604051903d90823e3d90fd5b90602093611ab0604493611137565b935090611a0f565b6040513d86823e3d90fd5b91959450919081811690308203611ae1575050506113619350611e8d565b606460009182602094959796604051927f23b872dd00000000000000000000000000000000000000000000000000000000845260048401528760248401528960448401525af1601f3d11600160005114163d15171615611b42575050505050565b60849550604051947fa8dced90000000000000000000000000000000000000000000000000000000008652600486015260248501521660448301526064820152fd5b50864710156119c2565b9260609192611c11946001600160a01b03809560409788958651978896879586957f3eece7db000000000000000000000000000000000000000000000000000000008752166004860152805160248601526020810151151560448601528881015115156064860152015160030b608484015260c060a484015260c48301906112dc565b03916000968791165af1918215611c6a5780938193611c32575b5050509091565b919350915082813d8111611c63575b611c4b8183611167565b810103126105ef575060208151910151388080611c2b565b503d611c41565b8351903d90823e3d90fd5b8051907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb91828101818111611d4e57601f1992838211611d7d57805183601511611d4e578311611d245781611cda575050505050604051600081526020810160405290565b9190601560405195601f8316801560051b9182828a01019586010195010101925b808310611d115750601f92508452011660405290565b8351835260209384019390920191611cfb565b60046040517f326b3d3a000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60046040517f648fb3b1000000000000000000000000000000000000000000000000000000008152fd5b611e3992916001600160a01b0380821615611e49575b61086d611dca8551611902565b9092908015611e3d57637fffffff905b60405196611de7886110d0565b8752151560208701526001604087015260030b60608601526040519586916020808401526020611e22835160408087015260808601906112dc565b92015116606083015203601f198101865285611167565b5090565b637fffffff1990611dda565b309150611dbd565b51906fffffffffffffffffffffffffffffffff821682036111dd57565b51908160070b82036111dd57565b519063ffffffff821682036111dd57565b9190916020600060446040517fa9059cbb00000000000000000000000000000000000000000000000000000000815286600482015285602482015282855af1601f3d11600160005114163d15171615611ee557505050565b60649350604051927fbf182be80000000000000000000000000000000000000000000000000000000084526001600160a01b0380921660048501521660248301526044820152fd5b90611f42575080511561184c57805190602001fd5b81511580611f8d575b611f53575090565b6024906001600160a01b03604051917f9996b315000000000000000000000000000000000000000000000000000000008352166004820152fd5b50803b15611f4b565b908060030b90600082126000146123475760000360030b5b63ffffffff80809416911602918216828103611d4e576204eb4a106123165760018216156122ed5770ffffffffffffffffffffffffffffffffff6ffffcb933bd6fad9d3af5f0b9f25db4d65b1690600283166122d1575b600483166122b5575b60088316612299575b6010831661227d575b60208316612261575b60408316612245575b60809283811661222a575b610100811661220f575b61020081166121f4575b61040081166121d9575b61080081166121be575b61100081166121a3575b6120008116612188575b614000811661216d575b6180008116612152575b620100008116612137575b62020000811661211c575b6204000016612102575b6000126120c4575b670de0b6b3a764000002901c90565b80156120d357600019046120b5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6d2216e584f630389b2052b8db590e909102821c906120ad565b6e5d6af8dedbcb3a6ccb7ce618d14225909202831c916120a3565b916f09aa508b5b7e5a9780b0cc4e25d61a5602831c91612098565b916f31be135f97da6e09a19dc367e3b6da4002831c9161208d565b916f70d869a156ddd32a39e257bc3f50aa9b02831c91612083565b916fa9f746462d8f7dd10e744d913d03333302831c91612079565b916fd097f3bdfd254ee83bdd3f248e7e785e02831c9161206f565b916fe7159475a2c578ef4f1d17b2b235d48002831c91612065565b916ff3392b0822b88206f8abe8a3b44dd9be02831c9161205b565b916ff987a7253ac4d9194200696907cf2e3702831c91612051565b916ffcbe86c7900aecf64236ab31f1f9dcb502831c91612047565b916ffe5dee046a99d51e2cc356c2f617dbe002831c9161203d565b906fff2ea16466c9838804e327cb417cafcb0260801c90612032565b906fff973b41fa98cd2e57b660be99eb2c4a0260801c90612029565b906fffcb9843d60f67b19e8887e0bd251eb70260801c90612020565b906fffe5caca7e10e81259b3cddc7a0649410260801c90612017565b906ffff2e50f5f656ac9229c67059486f3890260801c9061200e565b906ffff97272373d41fd789c8cb37ffcaa1c0260801c90612005565b70ffffffffffffffffffffffffffffffffff700100000000000000000000000000000000611ffa565b602490604051907f20ab18100000000000000000000000000000000000000000000000000000000082526004820152fd5b611fae565b9091928381039160009481604e1c158061241b575b61240a575b84156123fd5781156123c7576123bb6123c2956123b585876123b0633b9aca009661239b612394858b612490565b91876124be565b0160011c976123aa89806124dc565b956124dc565b61257b565b016125ff565b020161257b565b901c90565b6123d59150809392946124be565b90928082029281146123f4575b81830414901517156111dd5704901c90565b600193506123e2565b5090506123c29250612490565b6039955093851b9390851b90612366565b5084604e1c15612361565b9192939082156124885790818592156124805761245561245c9361246b9561244e88866124be565b0193612490565b0190612490565b670de0b6b3a7640000026125ff565b90818111908218021890818110908218021890565b505050505090565b505050905090565b670de0b6b3a7640000908181029183156124b5575b81830414901517156111dd570490565b600193506124a5565b8181029181830414901517156111dd57670de0b6b3a7640000900490565b90808202906000198184099082808310920391808303921461256a57670de0b6b3a76400009082821115612540577faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac10669940990828211900360ee1b910360121c170290565b60046040517f227bc153000000000000000000000000000000000000000000000000000000008152fd5b5050670de0b6b3a764000091500490565b909182820291600019848209938380861095039480860395146125f157848311156125405782910981600003821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b5050809250156120d3570490565b60b581710100000000000000000000000000000000008110156126b4575b806901000000000000000000620100009210156126a7575b6501000000000081101561269a575b630100000081101561268d575b010260121c60019080830401811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c8080920410900390565b60101c9160081b91612651565b60201c9160101b91612644565b60401c9160201b91612635565b5068b500000000000000009050608082901c61261d56fea2646970667358221220463767556635a4cc7907ee65d20bb1c96747026a0ad612bf9e6054830facfd7364736f6c634300081900330000000000000000000000000a7e848aca42d879ef06507fca0e7b33a0a63c1e000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Deployed Bytecode
0x60406080815260049081361015610074575b361561001c57600080fd5b6001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216330361004e57005b517fc0f54629000000000000000000000000000000000000000000000000000000008152fd5b600060e08135811c90816312210e8a146110bc5781631841ad6d1461100157816319b871d314610f8157816328a5b3c914610ee75781633fc8cef314610ea357816349404b7c14610e83578163522ba7eb14610c3a578163670ca18114610b7f57816367ca7c911461095657816369b027ab146108dd578163a3b105ca146108be578163a4af5a7f146107fb578163a6990946146107aa578163ac9650d8146105f2578163b800a206146105a6578163b9e45300146101c557508063c45a01551461017d578063df2ab5bb1461016a5763f16d7904146101545750610011565b6101676101603661131c565b9091611e8d565b80f35b506101676101773661131c565b91611706565b5090346101c157816003193601126101c157602090516001600160a01b037f0000000000000000000000000a7e848aca42d879ef06507fca0e7b33a0a63c1e168152f35b5080fd5b8484849260606003193601126105a2576101dd611200565b91602435916001600160a01b03604435941682517f1865c57d00000000000000000000000000000000000000000000000000000000815261012080828981865afa90811561048357899161048d575b5060a09150015160030b908351927f3256cfa900000000000000000000000000000000000000000000000000000000845282888501528084602481855afa938415610483579088949392918a946103a1575b50506020908551948580927fd0c93a7c0000000000000000000000000000000000000000000000000000000082525afa92831561039757889361035d575b506102db8360016102d08461030997611f96565b930160030b90611f96565b906fffffffffffffffffffffffffffffffff602081855116940151166103038383838761234c565b93612426565b908282108015610354575b61031c578580f35b6064955051937ffcb505c700000000000000000000000000000000000000000000000000000000855284015260248301526044820152fd5b50838211610314565b92506020833d60201161038f575b8161037860209383611167565b8101031261038b579151916102db6102bc565b8780fd5b3d915061036b565b84513d8a823e3d90fd5b919450809293503d831161047c575b6103ba8183611167565b8101918082840312610478578551926103d2846110d0565b6103db83611e51565b84526020916103ec60208501611e51565b60208601526103fc888501611e51565b8886015281607f8501121561047457875193610417856110d0565b84918101928311610470579060608c9897969594939201905b828210610449575050505060608201529160208a61027e565b839495969798509281929361045e8293611e7c565b81520191018b97969594939291610430565b8c80fd5b8b80fd5b8980fd5b503d6103b0565b85513d8b823e3d90fd5b80915082813d831161059b575b6104a48183611167565b8101031261059757845190810181811067ffffffffffffffff82111761056b5785526104cf82611e51565b81526104dd60208301611e51565b60208201526104ed858301611e6e565b858201526104fd60608301611e6e565b6060820152608082015164ffffffffff8116810361047857608082015260a08201518060030b81036104785760a082015261053a60c083016114ff565b60c082015261054a848301611e7c565b848201526101008092015160ff811681036104785760a0928201528961022c565b60248a60418b7f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b8880fd5b503d61049a565b8380fd5b505060a06003193601126105ef57506105e36105c0611200565b6105c8611216565b6105d061122c565b906105d9611281565b92606435916118a6565b82519182526020820152f35b80fd5b505082602091826003193601126105ef5781359167ffffffffffffffff908184116107a657366023850112156107a657830135908082116107a65760246005923660248260051b880101116107a2579261064b846116ab565b9561065889519788611167565b848752601f19610667866116ab565b0188875b8281106107925750505085917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbd82360301925b868110610720578a8a8a8a83519280840190808552835180925280868601968360051b870101940192955b8287106106d65785850386f35b909192938280610710837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08a6001960301865288516112dc565b96019201960195929190926106c9565b8481831b84010135848112156105975783018581013590878211610478576044019080360382136104785789808d610760600196956107769536916111a6565b80519101305af461076f6117f3565b9030611f2d565b610780828c6116c3565b5261078b818b6116c3565b500161069e565b60608a82018301528a910161066b565b8480fd5b8280fd5b82858560206003193601126107a6578135908142116107c7578380f35b6044935051917f3442e977000000000000000000000000000000000000000000000000000000008352820152426024820152fd5b50508260c06003193601126101c157610872610815611200565b61081d611216565b9061082661122c565b9061082f611281565b60a4359688519361083f856110d0565b6064358552151560208501528884015260030b60608301528651923360208501526020845261086d8461111b565b611b8e565b91909280831061088a57505082519182526020820152f35b916044928551927f84ae11480000000000000000000000000000000000000000000000000000000084528301526024820152fd5b6020846108d66108cd3661123b565b9392909261150c565b9051908152f35b8261090885876108ec36611291565b9592908551926108fb8461111b565b8352336020840152611da7565b508354928084116109225750506000196020935551908152f35b604493919251927f4956866a0000000000000000000000000000000000000000000000000000000084528301526024820152fd5b505091346107a65760806003193601126107a657610972611200565b602480359260643567ffffffffffffffff80821161038b573660238301121561038b57818301359681881161059757848301948884019281840192368411610474578915610b57576001600160a01b039a8b978d8351809a7f578eaca40000000000000000000000000000000000000000000000000000000082523384830152818860209d8e937f0000000000000000000000000a7e848aca42d879ef06507fca0e7b33a0a63c1e165afa918215610b4c5791610b13575b5015610aec57508703610a57575050505003126107a257359283168093036105a257610167923391611985565b91939490929996868287031261047457358381116104745782910180950312610478575197610a858961111b565b8284013591821161047857604492610a9f928501016111e2565b9182885201359283169283810361038b576015928701525111600014610add57505090610ad991610ad08251611c75565b82523390611da7565b5080f35b61016793508285553391611985565b82517f36294ff5000000000000000000000000000000000000000000000000000000008152fd5b90508981813d8311610b45575b610b2a8183611167565b81010312610b4157610b3b906114ff565b38610a2a565b8e80fd5b503d610b20565b8551903d90823e3d90fd5b8690517f63fa284a000000000000000000000000000000000000000000000000000000008152fd5b8260806003193601126105ef57610b94611200565b610b9c611216565b90604435606435916001600160a01b03807f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216908181841614600014610bfe5750505090610bef61016793923390611363565b610bf7611350565b3391611706565b8592951614600014610c295750610c2192610c1a913391611706565b3390611363565b610167611350565b919061016793610bf7913391611706565b838584610c4636611291565b9195929390610c5487611902565b909182908215610e105786517f0fc63d100000000000000000000000000000000000000000000000000000000081526020818b816001600160a01b0389165afa908115610e0657610cc19183918891610dd7575b509b94959b5b6001600160a01b03809d16903390611985565b82516015811194908515610dc9576029809110610da15790610d299392918501518c16905b8015610d9557637fffffff905b8a5193610cff856110d0565b845215156020840152878a84015260030b6060830152885192610d218461114b565b878452611b8e565b92159050610d4d57610d3a90611c75565b96610d4488611902565b91989192610cc1565b50935050808310610d62576020838351908152f35b90517f84ae1148000000000000000000000000000000000000000000000000000000008152928301526024820152604490fd5b637fffffff1990610cf3565b8a89517f41a6c181000000000000000000000000000000000000000000000000000000008152fd5b5090610d2992918990610ce6565b610df9915060203d602011610dff575b610df18183611167565b8101906114e0565b8d610ca8565b503d610de7565b88513d88823e3d90fd5b86517f5f64b55b0000000000000000000000000000000000000000000000000000000081526020818b816001600160a01b0389165afa908115610e0657610cc19183918891610e64575b509b94959b610cae565b610e7d915060203d602011610dff57610df18183611167565b8d610e5a565b8285856003193601126101c15761016790610e9c611216565b9035611363565b8284346101c157816003193601126101c157602090516001600160a01b037f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2168152f35b849291506003193601126105ef5750610efe611200565b610f06611216565b91610f2c610f1261122c565b610f1a611281565b9060a4359560c43595606435916118a6565b929093808511610f4c575080831061088a57505082519182526020820152f35b82856044928851927f4956866a0000000000000000000000000000000000000000000000000000000084528301526024820152fd5b505082610fa8610f903661123b565b965091929091908215610ff557637fffffff936118a6565b919092808411610fc057505082519182526020820152f35b90836044928651927f4956866a0000000000000000000000000000000000000000000000000000000084528301526024820152fd5b637fffffff19936118a6565b505060206003193601126105ef5782359067ffffffffffffffff82116105ef575061102f90369084016111e2565b91825160498103611088576020836108d68660148101516001600160a01b0360288301518116602984015192600160ff603987015160496fffffffffffffffffffffffffffffffff98015188169716951614921661150c565b60449251917fd137d34b00000000000000000000000000000000000000000000000000000000835282015260496024820152fd5b82806003193601126105ef57610167611350565b6080810190811067ffffffffffffffff8211176110ec57604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040810190811067ffffffffffffffff8211176110ec57604052565b67ffffffffffffffff81116110ec57604052565b6020810190811067ffffffffffffffff8211176110ec57604052565b90601f601f19910116810190811067ffffffffffffffff8211176110ec57604052565b67ffffffffffffffff81116110ec57601f01601f191660200190565b9291926111b28261118a565b916111c06040519384611167565b8294818452818301116111dd578281602093846000960137010152565b600080fd5b9080601f830112156111dd578160206111fd933591016111a6565b90565b600435906001600160a01b03821682036111dd57565b602435906001600160a01b03821682036111dd57565b6044359081151582036111dd57565b60031960a09101126111dd576001600160a01b039060043582811681036111dd579160243590811681036111dd579060443580151581036111dd57906064359060843590565b608435908160030b82036111dd57565b9060806003198301126111dd576004356001600160a01b03811681036111dd57916024359067ffffffffffffffff82116111dd576112d1916004016111e2565b906044359060643590565b919082519283825260005b848110611308575050601f19601f8460006020809697860101520116010190565b6020818301810151848301820152016112e7565b60031960609101126111dd576001600160a01b0360043581811681036111dd57916024359160443590811681036111dd5790565b4761135757565b6113614733611823565b565b6001600160a01b03807f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21692604051927f70a08231000000000000000000000000000000000000000000000000000000008452306004850152602084602481885afa938415611457576000946114ac575b508084106114635750826113e9575b50505050565b833b156111dd57600080946024604051809781937f2e1a7d4d0000000000000000000000000000000000000000000000000000000083528860048401525af19384156114575761143f94611448575b5016611823565b388080806113e3565b61145190611137565b38611438565b6040513d6000823e3d90fd5b6040517fd1cd07af0000000000000000000000000000000000000000000000000000000081526001600160a01b0386166004820152602481019190915260448101849052606490fd5b90936020823d6020116114d8575b816114c760209383611167565b810103126105ef57505192386113d4565b3d91506114ba565b908160209103126111dd57516001600160a01b03811681036111dd5790565b519081151582036111dd57565b93949391929091831561163657604051937f0fc63d100000000000000000000000000000000000000000000000000000000085526020856004816001600160a01b0388165afa8015611457578361157d916115c597600091611617575b505b6001600160a01b038716903390611985565b801561160b57637fffffff905b60405193611597856110d0565b8452151560208401526000604084015260030b6060830152604051926115bc8461114b565b60008452611b8e565b929050828181106115d4575050565b60449250604051917f84ae114800000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b637fffffff199061158a565b611630915060203d602011610dff57610df18183611167565b38611569565b604051937f5f64b55b0000000000000000000000000000000000000000000000000000000085526020856004816001600160a01b0388165afa8015611457578361157d916115c59760009161168c575b5061156b565b6116a5915060203d602011610dff57610df18183611167565b38611686565b67ffffffffffffffff81116110ec5760051b60200190565b80518210156116d75760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b916001600160a01b03831691604051927f70a08231000000000000000000000000000000000000000000000000000000008452306004850152602084602481845afa938415611457576000946117bf575b508184106117745750508161176b57505050565b61136192611e8d565b6040517fd1cd07af0000000000000000000000000000000000000000000000000000000081526001600160a01b03919091166004820152602481019190915260448101839052606490fd5b90936020823d6020116117eb575b816117da60209383611167565b810103126105ef5750519238611757565b3d91506117cd565b3d1561181e573d906118048261118a565b916118126040519384611167565b82523d6000602084013e565b606090565b8147106118765760008080936001600160a01b038294165af16118446117f3565b501561184c57565b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b60246040517fcd786059000000000000000000000000000000000000000000000000000000008152306004820152fd5b92936118f994604051936118b9856110d0565b8452151560208401526001604084015260030b60608301526001600160a01b0381166118fd5750305b604051923360208501526020845261086d8461111b565b9091565b6118e2565b90601482511061195b5760148201516001600160a01b0316916015815110611931576015015160ff1660011490565b60046040517f7c1be900000000000000000000000000000000000000000000000000000000008152fd5b60046040517f41a6c181000000000000000000000000000000000000000000000000000000008152fd5b9190916001600160a01b039081811690827f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2169485831480611b84575b15611ac357505050823b156111dd57604051917fd0e30db0000000000000000000000000000000000000000000000000000000008352600092838160048189895af18015611ab857611aa1575b50604490836020949560405197889586947fa9059cbb00000000000000000000000000000000000000000000000000000000865216600485015260248401525af18015611a9457611a5e575050565b6020823d602011611a8c575b81611a7760209383611167565b810103126105ef5750611a89906114ff565b50565b3d9150611a6a565b50604051903d90823e3d90fd5b90602093611ab0604493611137565b935090611a0f565b6040513d86823e3d90fd5b91959450919081811690308203611ae1575050506113619350611e8d565b606460009182602094959796604051927f23b872dd00000000000000000000000000000000000000000000000000000000845260048401528760248401528960448401525af1601f3d11600160005114163d15171615611b42575050505050565b60849550604051947fa8dced90000000000000000000000000000000000000000000000000000000008652600486015260248501521660448301526064820152fd5b50864710156119c2565b9260609192611c11946001600160a01b03809560409788958651978896879586957f3eece7db000000000000000000000000000000000000000000000000000000008752166004860152805160248601526020810151151560448601528881015115156064860152015160030b608484015260c060a484015260c48301906112dc565b03916000968791165af1918215611c6a5780938193611c32575b5050509091565b919350915082813d8111611c63575b611c4b8183611167565b810103126105ef575060208151910151388080611c2b565b503d611c41565b8351903d90823e3d90fd5b8051907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffeb91828101818111611d4e57601f1992838211611d7d57805183601511611d4e578311611d245781611cda575050505050604051600081526020810160405290565b9190601560405195601f8316801560051b9182828a01019586010195010101925b808310611d115750601f92508452011660405290565b8351835260209384019390920191611cfb565b60046040517f326b3d3a000000000000000000000000000000000000000000000000000000008152fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60046040517f648fb3b1000000000000000000000000000000000000000000000000000000008152fd5b611e3992916001600160a01b0380821615611e49575b61086d611dca8551611902565b9092908015611e3d57637fffffff905b60405196611de7886110d0565b8752151560208701526001604087015260030b60608601526040519586916020808401526020611e22835160408087015260808601906112dc565b92015116606083015203601f198101865285611167565b5090565b637fffffff1990611dda565b309150611dbd565b51906fffffffffffffffffffffffffffffffff821682036111dd57565b51908160070b82036111dd57565b519063ffffffff821682036111dd57565b9190916020600060446040517fa9059cbb00000000000000000000000000000000000000000000000000000000815286600482015285602482015282855af1601f3d11600160005114163d15171615611ee557505050565b60649350604051927fbf182be80000000000000000000000000000000000000000000000000000000084526001600160a01b0380921660048501521660248301526044820152fd5b90611f42575080511561184c57805190602001fd5b81511580611f8d575b611f53575090565b6024906001600160a01b03604051917f9996b315000000000000000000000000000000000000000000000000000000008352166004820152fd5b50803b15611f4b565b908060030b90600082126000146123475760000360030b5b63ffffffff80809416911602918216828103611d4e576204eb4a106123165760018216156122ed5770ffffffffffffffffffffffffffffffffff6ffffcb933bd6fad9d3af5f0b9f25db4d65b1690600283166122d1575b600483166122b5575b60088316612299575b6010831661227d575b60208316612261575b60408316612245575b60809283811661222a575b610100811661220f575b61020081166121f4575b61040081166121d9575b61080081166121be575b61100081166121a3575b6120008116612188575b614000811661216d575b6180008116612152575b620100008116612137575b62020000811661211c575b6204000016612102575b6000126120c4575b670de0b6b3a764000002901c90565b80156120d357600019046120b5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6d2216e584f630389b2052b8db590e909102821c906120ad565b6e5d6af8dedbcb3a6ccb7ce618d14225909202831c916120a3565b916f09aa508b5b7e5a9780b0cc4e25d61a5602831c91612098565b916f31be135f97da6e09a19dc367e3b6da4002831c9161208d565b916f70d869a156ddd32a39e257bc3f50aa9b02831c91612083565b916fa9f746462d8f7dd10e744d913d03333302831c91612079565b916fd097f3bdfd254ee83bdd3f248e7e785e02831c9161206f565b916fe7159475a2c578ef4f1d17b2b235d48002831c91612065565b916ff3392b0822b88206f8abe8a3b44dd9be02831c9161205b565b916ff987a7253ac4d9194200696907cf2e3702831c91612051565b916ffcbe86c7900aecf64236ab31f1f9dcb502831c91612047565b916ffe5dee046a99d51e2cc356c2f617dbe002831c9161203d565b906fff2ea16466c9838804e327cb417cafcb0260801c90612032565b906fff973b41fa98cd2e57b660be99eb2c4a0260801c90612029565b906fffcb9843d60f67b19e8887e0bd251eb70260801c90612020565b906fffe5caca7e10e81259b3cddc7a0649410260801c90612017565b906ffff2e50f5f656ac9229c67059486f3890260801c9061200e565b906ffff97272373d41fd789c8cb37ffcaa1c0260801c90612005565b70ffffffffffffffffffffffffffffffffff700100000000000000000000000000000000611ffa565b602490604051907f20ab18100000000000000000000000000000000000000000000000000000000082526004820152fd5b611fae565b9091928381039160009481604e1c158061241b575b61240a575b84156123fd5781156123c7576123bb6123c2956123b585876123b0633b9aca009661239b612394858b612490565b91876124be565b0160011c976123aa89806124dc565b956124dc565b61257b565b016125ff565b020161257b565b901c90565b6123d59150809392946124be565b90928082029281146123f4575b81830414901517156111dd5704901c90565b600193506123e2565b5090506123c29250612490565b6039955093851b9390851b90612366565b5084604e1c15612361565b9192939082156124885790818592156124805761245561245c9361246b9561244e88866124be565b0193612490565b0190612490565b670de0b6b3a7640000026125ff565b90818111908218021890818110908218021890565b505050505090565b505050905090565b670de0b6b3a7640000908181029183156124b5575b81830414901517156111dd570490565b600193506124a5565b8181029181830414901517156111dd57670de0b6b3a7640000900490565b90808202906000198184099082808310920391808303921461256a57670de0b6b3a76400009082821115612540577faccb18165bd6fe31ae1cf318dc5b51eee0e1ba569b88cd74c1773b91fac10669940990828211900360ee1b910360121c170290565b60046040517f227bc153000000000000000000000000000000000000000000000000000000008152fd5b5050670de0b6b3a764000091500490565b909182820291600019848209938380861095039480860395146125f157848311156125405782910981600003821680920460028082600302188083028203028083028203028083028203028083028203028083028203028092029003029360018380600003040190848311900302920304170290565b5050809250156120d3570490565b60b581710100000000000000000000000000000000008110156126b4575b806901000000000000000000620100009210156126a7575b6501000000000081101561269a575b630100000081101561268d575b010260121c60019080830401811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c8080920410900390565b60101c9160081b91612651565b60201c9160101b91612644565b60401c9160201b91612635565b5068b500000000000000009050608082901c61261d56fea2646970667358221220463767556635a4cc7907ee65d20bb1c96747026a0ad612bf9e6054830facfd7364736f6c63430008190033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000a7e848aca42d879ef06507fca0e7b33a0a63c1e000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
-----Decoded View---------------
Arg [0] : _factory (address): 0x0A7e848Aca42d879EF06507Fca0E7b33A0a63c1e
Arg [1] : _weth (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000000a7e848aca42d879ef06507fca0e7b33a0a63c1e
Arg [1] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ZKSYNC | 100.00% | $3,413.81 | 0.00014738 | $0.503128 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.