Overview
S Balance
0 S
S Value
-More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 31 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Create LB Pair | 630356 | 4 hrs ago | IN | 0 S | 0.00033388 | ||||
Create LB Pair | 626133 | 4 hrs ago | IN | 0 S | 0.00033381 | ||||
Create LB Pair | 616915 | 6 hrs ago | IN | 0 S | 0.00033383 | ||||
Create LB Pair | 612058 | 7 hrs ago | IN | 0 S | 0.00029911 | ||||
Create LB Pair | 610950 | 7 hrs ago | IN | 0 S | 0.00031805 | ||||
Create LB Pair | 603222 | 8 hrs ago | IN | 0 S | 0.00071563 | ||||
Create LB Pair | 601962 | 8 hrs ago | IN | 0 S | 0.00071575 | ||||
Create LB Pair | 582581 | 11 hrs ago | IN | 0 S | 0.00031807 | ||||
Create LB Pair | 576764 | 11 hrs ago | IN | 0 S | 0.00031809 | ||||
Create LB Pair | 572510 | 12 hrs ago | IN | 0 S | 0.00031814 | ||||
Create LB Pair | 561712 | 13 hrs ago | IN | 0 S | 0.00031809 | ||||
Create LB Pair | 554307 | 14 hrs ago | IN | 0 S | 0.00071576 | ||||
Add Quote Asset | 554302 | 14 hrs ago | IN | 0 S | 0.00018708 | ||||
Create LB Pair | 483560 | 2 days ago | IN | 0 S | 0.00071579 | ||||
Create LB Pair | 483556 | 2 days ago | IN | 0 S | 0.00071574 | ||||
Add Quote Asset | 483551 | 2 days ago | IN | 0 S | 0.00018711 | ||||
Create LB Pair | 339470 | 6 days ago | IN | 0 S | 0.00033257 | ||||
Create LB Pair | 296542 | 7 days ago | IN | 0 S | 0.00033711 | ||||
Set Preset | 276498 | 8 days ago | IN | 0 S | 0.00011842 | ||||
Set Preset | 276495 | 8 days ago | IN | 0 S | 0.00011748 | ||||
Set Preset | 276491 | 8 days ago | IN | 0 S | 0.00011823 | ||||
Set Preset | 276488 | 8 days ago | IN | 0 S | 0.00011748 | ||||
Set Preset | 276485 | 8 days ago | IN | 0 S | 0.00011748 | ||||
Set Preset | 276482 | 8 days ago | IN | 0 S | 0.00011823 | ||||
Set Preset | 276479 | 8 days ago | IN | 0 S | 0.00011823 |
Latest 16 internal transactions
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
630356 | 4 hrs ago | Contract Creation | 0 S | |||
626133 | 4 hrs ago | Contract Creation | 0 S | |||
616915 | 6 hrs ago | Contract Creation | 0 S | |||
612058 | 7 hrs ago | Contract Creation | 0 S | |||
610950 | 7 hrs ago | Contract Creation | 0 S | |||
603222 | 8 hrs ago | Contract Creation | 0 S | |||
601962 | 8 hrs ago | Contract Creation | 0 S | |||
582581 | 11 hrs ago | Contract Creation | 0 S | |||
576764 | 11 hrs ago | Contract Creation | 0 S | |||
572510 | 12 hrs ago | Contract Creation | 0 S | |||
561712 | 13 hrs ago | Contract Creation | 0 S | |||
554307 | 14 hrs ago | Contract Creation | 0 S | |||
483560 | 2 days ago | Contract Creation | 0 S | |||
483556 | 2 days ago | Contract Creation | 0 S | |||
339470 | 6 days ago | Contract Creation | 0 S | |||
296542 | 7 days ago | Contract Creation | 0 S |
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 Name:
LBFactory
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 360 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.20; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Ownable2Step, Ownable} from "@openzeppelin/contracts/access/Ownable2Step.sol"; import {PairParameterHelper} from "./libraries/PairParameterHelper.sol"; import {Encoded} from "./libraries/math/Encoded.sol"; import {ImmutableClone} from "./libraries/ImmutableClone.sol"; import {PriceHelper} from "./libraries/PriceHelper.sol"; import {SafeCast} from "./libraries/math/SafeCast.sol"; import {Hooks} from "./libraries/Hooks.sol"; import {ILBFactory} from "./interfaces/ILBFactory.sol"; import {ILBPair} from "./interfaces/ILBPair.sol"; import {ILBHooks} from "./interfaces/ILBHooks.sol"; /** * @title Liquidity Book Factory * @author Trader Joe * @notice Contract used to deploy and register new LBPairs. * Enables setting fee parameters, flashloan fees and LBPair implementation. * Unless the `isOpen` is `true`, only the owner of the factory can create pairs. */ contract LBFactory is Ownable2Step, AccessControl, ILBFactory { using SafeCast for uint256; using Encoded for bytes32; using PairParameterHelper for bytes32; using EnumerableSet for EnumerableSet.AddressSet; using EnumerableSet for EnumerableSet.UintSet; using EnumerableMap for EnumerableMap.UintToUintMap; bytes32 public constant LB_HOOKS_MANAGER_ROLE = keccak256("LB_HOOKS_MANAGER_ROLE"); uint256 private constant _OFFSET_IS_PRESET_OPEN = 255; uint256 private constant _MIN_BIN_STEP = 1; // 0.001% uint256 private constant _MAX_FLASHLOAN_FEE = 0.1e18; // 10% address private _feeRecipient; uint256 private _flashLoanFee; address private _lbPairImplementation; ILBPair[] private _allLBPairs; /** * @dev Mapping from a (tokenA, tokenB, binStep) to a LBPair. The tokens are ordered to save gas, but they can be * in the reverse order in the actual pair. * Always query one of the 2 tokens of the pair to assert the order of the 2 tokens */ mapping(IERC20 => mapping(IERC20 => mapping(uint256 => LBPairInformation))) private _lbPairsInfo; EnumerableMap.UintToUintMap private _presets; EnumerableSet.AddressSet private _quoteAssetWhitelist; /** * @dev Mapping from a (tokenA, tokenB) to a set of available bin steps, this is used to keep track of the * bin steps that are already used for a pair. * The tokens are ordered to save gas, but they can be in the reverse order in the actual pair. * Always query one of the 2 tokens of the pair to assert the order of the 2 tokens */ mapping(IERC20 => mapping(IERC20 => EnumerableSet.UintSet)) private _availableLBPairBinSteps; /** * @notice Constructor * @param feeRecipient The address of the fee recipient * @param flashLoanFee The value of the fee for flash loan */ constructor(address feeRecipient, address initialOwner, uint256 flashLoanFee) Ownable(initialOwner) { if (flashLoanFee > _MAX_FLASHLOAN_FEE) revert LBFactory__FlashLoanFeeAboveMax(flashLoanFee, _MAX_FLASHLOAN_FEE); _setFeeRecipient(feeRecipient); _flashLoanFee = flashLoanFee; emit FlashLoanFeeSet(0, flashLoanFee); } /** * @notice Get the minimum bin step a pair can have * @return minBinStep */ function getMinBinStep() external pure override returns (uint256 minBinStep) { return _MIN_BIN_STEP; } /** * @notice Get the protocol fee recipient * @return feeRecipient */ function getFeeRecipient() external view override returns (address feeRecipient) { return _feeRecipient; } /** * @notice Get the maximum fee percentage for flashLoans * @return maxFee */ function getMaxFlashLoanFee() external pure override returns (uint256 maxFee) { return _MAX_FLASHLOAN_FEE; } /** * @notice Get the fee for flash loans, in 1e18 * @return flashLoanFee The fee for flash loans, in 1e18 */ function getFlashLoanFee() external view override returns (uint256 flashLoanFee) { return _flashLoanFee; } /** * @notice Get the address of the LBPair implementation * @return lbPairImplementation The address of the LBPair implementation */ function getLBPairImplementation() external view override returns (address lbPairImplementation) { return _lbPairImplementation; } /** * @notice View function to return the number of LBPairs created * @return lbPairNumber */ function getNumberOfLBPairs() external view override returns (uint256 lbPairNumber) { return _allLBPairs.length; } /** * @notice View function to return the LBPair created at index `index` * @param index The index * @return lbPair The address of the LBPair at index `index` */ function getLBPairAtIndex(uint256 index) external view override returns (ILBPair lbPair) { return _allLBPairs[index]; } /** * @notice View function to return the number of quote assets whitelisted * @return numberOfQuoteAssets The number of quote assets */ function getNumberOfQuoteAssets() external view override returns (uint256 numberOfQuoteAssets) { return _quoteAssetWhitelist.length(); } /** * @notice View function to return the quote asset whitelisted at index `index` * @param index The index * @return asset The address of the quoteAsset at index `index` */ function getQuoteAssetAtIndex(uint256 index) external view override returns (IERC20 asset) { return IERC20(_quoteAssetWhitelist.at(index)); } /** * @notice View function to return whether a token is a quotedAsset (true) or not (false) * @param token The address of the asset * @return isQuote Whether the token is a quote asset or not */ function isQuoteAsset(IERC20 token) external view override returns (bool isQuote) { return _quoteAssetWhitelist.contains(address(token)); } /** * @notice Returns the LBPairInformation if it exists, * if not, then the address 0 is returned. The order doesn't matter * @param tokenA The address of the first token of the pair * @param tokenB The address of the second token of the pair * @param binStep The bin step of the LBPair * @return lbPairInformation The LBPairInformation */ function getLBPairInformation(IERC20 tokenA, IERC20 tokenB, uint256 binStep) external view override returns (LBPairInformation memory lbPairInformation) { return _getLBPairInformation(tokenA, tokenB, binStep); } /** * @notice View function to return the different parameters of the preset * Will revert if the preset doesn't exist * @param binStep The bin step of the preset * @return baseFactor The base factor * @return filterPeriod The filter period of the preset * @return decayPeriod The decay period of the preset * @return reductionFactor The reduction factor of the preset * @return variableFeeControl The variable fee control of the preset * @return protocolShare The protocol share of the preset * @return maxVolatilityAccumulator The max volatility accumulator of the preset * @return isOpen Whether the preset is open or not */ function getPreset(uint256 binStep) external view override returns ( uint256 baseFactor, uint256 filterPeriod, uint256 decayPeriod, uint256 reductionFactor, uint256 variableFeeControl, uint256 protocolShare, uint256 maxVolatilityAccumulator, bool isOpen ) { if (!_presets.contains(binStep)) revert LBFactory__BinStepHasNoPreset(binStep); bytes32 preset = bytes32(_presets.get(binStep)); baseFactor = preset.getBaseFactor(); filterPeriod = preset.getFilterPeriod(); decayPeriod = preset.getDecayPeriod(); reductionFactor = preset.getReductionFactor(); variableFeeControl = preset.getVariableFeeControl(); protocolShare = preset.getProtocolShare(); maxVolatilityAccumulator = preset.getMaxVolatilityAccumulator(); isOpen = preset.decodeBool(_OFFSET_IS_PRESET_OPEN); } /** * @notice View function to return the list of available binStep with a preset * @return binStepWithPreset The list of binStep */ function getAllBinSteps() external view override returns (uint256[] memory binStepWithPreset) { return _presets.keys(); } /** * @notice View function to return the list of open binSteps * @return openBinStep The list of open binSteps */ function getOpenBinSteps() external view override returns (uint256[] memory openBinStep) { uint256 length = _presets.length(); if (length > 0) { openBinStep = new uint256[](length); uint256 index; for (uint256 i; i < length; ++i) { (uint256 binStep, uint256 preset) = _presets.at(i); if (_isPresetOpen(bytes32(preset))) { openBinStep[index] = binStep; index++; } } if (index < length) { assembly { mstore(openBinStep, index) } } } } /** * @notice View function to return all the LBPair of a pair of tokens * @param tokenX The first token of the pair * @param tokenY The second token of the pair * @return lbPairsAvailable The list of available LBPairs */ function getAllLBPairs(IERC20 tokenX, IERC20 tokenY) external view override returns (LBPairInformation[] memory lbPairsAvailable) { unchecked { (IERC20 tokenA, IERC20 tokenB) = _sortTokens(tokenX, tokenY); EnumerableSet.UintSet storage addressSet = _availableLBPairBinSteps[tokenA][tokenB]; uint256 length = addressSet.length(); if (length > 0) { lbPairsAvailable = new LBPairInformation[](length); mapping(uint256 => LBPairInformation) storage lbPairsInfo = _lbPairsInfo[tokenA][tokenB]; for (uint256 i = 0; i < length; ++i) { uint16 binStep = addressSet.at(i).safe16(); lbPairsAvailable[i] = LBPairInformation({ binStep: binStep, LBPair: lbPairsInfo[binStep].LBPair, createdByOwner: lbPairsInfo[binStep].createdByOwner, ignoredForRouting: lbPairsInfo[binStep].ignoredForRouting }); } } } } /** * @notice Set the LBPair implementation address * @dev Needs to be called by the owner * @param newLBPairImplementation The address of the implementation */ function setLBPairImplementation(address newLBPairImplementation) external override onlyOwner { if (ILBPair(newLBPairImplementation).getFactory() != this) { revert LBFactory__LBPairSafetyCheckFailed(newLBPairImplementation); } address oldLBPairImplementation = _lbPairImplementation; if (oldLBPairImplementation == newLBPairImplementation) { revert LBFactory__SameImplementation(newLBPairImplementation); } _lbPairImplementation = newLBPairImplementation; emit LBPairImplementationSet(oldLBPairImplementation, newLBPairImplementation); } /** * @notice Create a liquidity bin LBPair for tokenX and tokenY * @param tokenX The address of the first token * @param tokenY The address of the second token * @param activeId The active id of the pair * @param binStep The bin step in basis point, used to calculate log(1 + binStep / 10_000) * @return pair The address of the newly created LBPair */ function createLBPair(IERC20 tokenX, IERC20 tokenY, uint24 activeId, uint16 binStep) external override returns (ILBPair pair) { if (!_presets.contains(binStep)) revert LBFactory__BinStepHasNoPreset(binStep); bytes32 preset = bytes32(_presets.get(binStep)); bool isOwner = msg.sender == owner(); if (!_isPresetOpen(preset) && !isOwner) { revert LBFactory__PresetIsLockedForUsers(msg.sender, binStep); } if (!_quoteAssetWhitelist.contains(address(tokenY))) revert LBFactory__QuoteAssetNotWhitelisted(tokenY); if (tokenX == tokenY) revert LBFactory__IdenticalAddresses(tokenX); // safety check, making sure that the price can be calculated PriceHelper.getPriceFromId(activeId, binStep); // We sort token for storage efficiency, only one input needs to be stored because they are sorted (IERC20 tokenA, IERC20 tokenB) = _sortTokens(tokenX, tokenY); // single check is sufficient if (address(tokenA) == address(0)) revert LBFactory__AddressZero(); if (address(_lbPairsInfo[tokenA][tokenB][binStep].LBPair) != address(0)) { revert LBFactory__LBPairAlreadyExists(tokenX, tokenY, binStep); } { address implementation = _lbPairImplementation; if (implementation == address(0)) revert LBFactory__ImplementationNotSet(); pair = ILBPair( ImmutableClone.cloneDeterministic( implementation, abi.encodePacked(tokenX, tokenY, binStep), keccak256(abi.encode(tokenA, tokenB, binStep)) ) ); } _lbPairsInfo[tokenA][tokenB][binStep] = LBPairInformation({binStep: binStep, LBPair: pair, createdByOwner: isOwner, ignoredForRouting: false}); _allLBPairs.push(pair); _availableLBPairBinSteps[tokenA][tokenB].add(binStep); emit LBPairCreated(tokenX, tokenY, binStep, pair, _allLBPairs.length - 1); pair.initialize( preset.getBaseFactor(), preset.getFilterPeriod(), preset.getDecayPeriod(), preset.getReductionFactor(), preset.getVariableFeeControl(), preset.getProtocolShare(), preset.getMaxVolatilityAccumulator(), activeId ); } /** * @notice Function to set whether the pair is ignored or not for routing, it will make the pair unusable by the router * @dev Needs to be called by the owner * Reverts if: * - The pair doesn't exist * - The ignored state is already in the same state * @param tokenX The address of the first token of the pair * @param tokenY The address of the second token of the pair * @param binStep The bin step in basis point of the pair * @param ignored Whether to ignore (true) or not (false) the pair for routing */ function setLBPairIgnored(IERC20 tokenX, IERC20 tokenY, uint16 binStep, bool ignored) external override onlyOwner { (IERC20 tokenA, IERC20 tokenB) = _sortTokens(tokenX, tokenY); LBPairInformation memory pairInformation = _lbPairsInfo[tokenA][tokenB][binStep]; if (address(pairInformation.LBPair) == address(0)) { revert LBFactory__LBPairDoesNotExist(tokenX, tokenY, binStep); } if (pairInformation.ignoredForRouting == ignored) revert LBFactory__LBPairIgnoredIsAlreadyInTheSameState(); _lbPairsInfo[tokenA][tokenB][binStep].ignoredForRouting = ignored; emit LBPairIgnoredStateChanged(pairInformation.LBPair, ignored); } /** * @notice Sets the preset parameters of a bin step * @dev Needs to be called by the owner * Reverts if: * - The binStep is lower than the minimum bin step * @param binStep The bin step in basis point, used to calculate the price * @param baseFactor The base factor, used to calculate the base fee, baseFee = baseFactor * binStep * @param filterPeriod The period where the accumulator value is untouched, prevent spam * @param decayPeriod The period where the accumulator value is decayed, by the reduction factor * @param reductionFactor The reduction factor, used to calculate the reduction of the accumulator * @param variableFeeControl The variable fee control, used to control the variable fee, can be 0 to disable it * @param protocolShare The share of the fees received by the protocol * @param maxVolatilityAccumulator The max value of the volatility accumulator */ function setPreset( uint16 binStep, uint16 baseFactor, uint16 filterPeriod, uint16 decayPeriod, uint16 reductionFactor, uint24 variableFeeControl, uint16 protocolShare, uint24 maxVolatilityAccumulator, bool isOpen ) external override onlyOwner { if (binStep < _MIN_BIN_STEP) revert LBFactory__BinStepTooLow(binStep); bytes32 preset = bytes32(0).setStaticFeeParameters( baseFactor, filterPeriod, decayPeriod, reductionFactor, variableFeeControl, protocolShare, maxVolatilityAccumulator ); if (isOpen) { preset = preset.setBool(true, _OFFSET_IS_PRESET_OPEN); } _presets.set(binStep, uint256(preset)); emit PresetSet( binStep, baseFactor, filterPeriod, decayPeriod, reductionFactor, variableFeeControl, protocolShare, maxVolatilityAccumulator ); emit PresetOpenStateChanged(binStep, isOpen); } /** * @notice Sets if the preset is open or not to be used by users * @dev Needs to be called by the owner * Reverts if: * - The binStep doesn't have a preset * - The preset is already in the same state * @param binStep The bin step in basis point, used to calculate the price * @param isOpen Whether the preset is open or not */ function setPresetOpenState(uint16 binStep, bool isOpen) external override onlyOwner { if (!_presets.contains(binStep)) revert LBFactory__BinStepHasNoPreset(binStep); bytes32 preset = bytes32(_presets.get(binStep)); if (preset.decodeBool(_OFFSET_IS_PRESET_OPEN) == isOpen) { revert LBFactory__PresetOpenStateIsAlreadyInTheSameState(); } _presets.set(binStep, uint256(preset.setBool(isOpen, _OFFSET_IS_PRESET_OPEN))); emit PresetOpenStateChanged(binStep, isOpen); } /** * @notice Remove the preset linked to a binStep * @dev Needs to be called by the owner * Reverts if: * - The binStep doesn't have a preset * @param binStep The bin step to remove */ function removePreset(uint16 binStep) external override onlyOwner { if (!_presets.remove(binStep)) revert LBFactory__BinStepHasNoPreset(binStep); emit PresetRemoved(binStep); } /** * @notice Function to set the fee parameter of a LBPair * @dev Needs to be called by the owner * Reverts if: * - The pair doesn't exist * @param tokenX The address of the first token * @param tokenY The address of the second token * @param binStep The bin step in basis point, used to calculate the price * @param baseFactor The base factor, used to calculate the base fee, baseFee = baseFactor * binStep * @param filterPeriod The period where the accumulator value is untouched, prevent spam * @param decayPeriod The period where the accumulator value is decayed, by the reduction factor * @param reductionFactor The reduction factor, used to calculate the reduction of the accumulator * @param variableFeeControl The variable fee control, used to control the variable fee, can be 0 to disable it * @param protocolShare The share of the fees received by the protocol * @param maxVolatilityAccumulator The max value of volatility accumulator */ function setFeesParametersOnPair( IERC20 tokenX, IERC20 tokenY, uint16 binStep, uint16 baseFactor, uint16 filterPeriod, uint16 decayPeriod, uint16 reductionFactor, uint24 variableFeeControl, uint16 protocolShare, uint24 maxVolatilityAccumulator ) external override onlyOwner { ILBPair lbPair = _getLBPairInformation(tokenX, tokenY, binStep).LBPair; if (address(lbPair) == address(0)) revert LBFactory__LBPairNotCreated(tokenX, tokenY, binStep); lbPair.setStaticFeeParameters( baseFactor, filterPeriod, decayPeriod, reductionFactor, variableFeeControl, protocolShare, maxVolatilityAccumulator ); } /** * @notice Function to set the hooks parameters of a pair * @dev Needs to be called by an address with the LB_HOOKS_MANAGER_ROLE * Reverts if: * - The pair doesn't exist * - The hooks is `address(0)` or the hooks flags are all false * @param tokenX The address of the first token * @param tokenY The address of the second token * @param binStep The bin step in basis point, used to calculate the price * @param hooksParameters The hooks parameters * @param onHooksSetData The data to pass to the onHooksSet function */ function setLBHooksParametersOnPair( IERC20 tokenX, IERC20 tokenY, uint16 binStep, bytes32 hooksParameters, bytes calldata onHooksSetData ) external override onlyRole(LB_HOOKS_MANAGER_ROLE) { if (Hooks.getHooks(hooksParameters) == address(0) || Hooks.getFlags(hooksParameters) == 0) { revert LBFactory__InvalidHooksParameters(); } _setLBHooksParametersOnPair(tokenX, tokenY, binStep, hooksParameters, onHooksSetData); } /** * @notice Function to remove the hooks contract from the pair * @dev Needs to be called by an address with the LB_HOOKS_MANAGER_ROLE * Reverts if: * - The pair doesn't exist * @param tokenX The address of the first token * @param tokenY The address of the second token * @param binStep The bin step in basis point, used to calculate the price */ function removeLBHooksOnPair(IERC20 tokenX, IERC20 tokenY, uint16 binStep) external override onlyRole(LB_HOOKS_MANAGER_ROLE) { _setLBHooksParametersOnPair(tokenX, tokenY, binStep, 0, new bytes(0)); } /** * @notice Function to set the recipient of the fees. This address needs to be able to receive ERC20s * @dev Needs to be called by the owner * Reverts if: * - The feeRecipient is `address(0)` * - The feeRecipient is the same as the current one * @param feeRecipient The address of the recipient */ function setFeeRecipient(address feeRecipient) external override onlyOwner { _setFeeRecipient(feeRecipient); } /** * @notice Function to set the flash loan fee * @dev Needs to be called by the owner * Reverts if: * - The flashLoanFee is the same as the current one * - The flashLoanFee is above the maximum flash loan fee * @param flashLoanFee The value of the fee for flash loan */ function setFlashLoanFee(uint256 flashLoanFee) external override onlyOwner { uint256 oldFlashLoanFee = _flashLoanFee; if (oldFlashLoanFee == flashLoanFee) revert LBFactory__SameFlashLoanFee(flashLoanFee); if (flashLoanFee > _MAX_FLASHLOAN_FEE) revert LBFactory__FlashLoanFeeAboveMax(flashLoanFee, _MAX_FLASHLOAN_FEE); _flashLoanFee = flashLoanFee; emit FlashLoanFeeSet(oldFlashLoanFee, flashLoanFee); } /** * @notice Function to add an asset to the whitelist of quote assets * @dev Needs to be called by the owner * Reverts if: * - The quoteAsset is already whitelisted * @param quoteAsset The quote asset (e.g: NATIVE, USDC...) */ function addQuoteAsset(IERC20 quoteAsset) external override onlyOwner { if (!_quoteAssetWhitelist.add(address(quoteAsset))) { revert LBFactory__QuoteAssetAlreadyWhitelisted(quoteAsset); } emit QuoteAssetAdded(quoteAsset); } /** * @notice Function to remove an asset from the whitelist of quote assets * @dev Needs to be called by the owner * Reverts if: * - The quoteAsset was not whitelisted * @param quoteAsset The quote asset (e.g: NATIVE, USDC...) */ function removeQuoteAsset(IERC20 quoteAsset) external override onlyOwner { if (!_quoteAssetWhitelist.remove(address(quoteAsset))) revert LBFactory__QuoteAssetNotWhitelisted(quoteAsset); emit QuoteAssetRemoved(quoteAsset); } function _isPresetOpen(bytes32 preset) internal pure returns (bool) { return preset.decodeBool(_OFFSET_IS_PRESET_OPEN); } /** * @notice Internal function to set the recipient of the fee * @param feeRecipient The address of the recipient */ function _setFeeRecipient(address feeRecipient) internal { if (feeRecipient == address(0)) revert LBFactory__AddressZero(); address oldFeeRecipient = _feeRecipient; if (oldFeeRecipient == feeRecipient) revert LBFactory__SameFeeRecipient(_feeRecipient); _feeRecipient = feeRecipient; emit FeeRecipientSet(oldFeeRecipient, feeRecipient); } /** * @notice Function to force the decay of the volatility accumulator of a pair * @dev Needs to be called by the owner * @param pair The pair to force the decay */ function forceDecay(ILBPair pair) external override onlyOwner { pair.forceDecay(); } /** * @notice Returns the LBPairInformation if it exists, * if not, then the address 0 is returned. The order doesn't matter * @param tokenA The address of the first token of the pair * @param tokenB The address of the second token of the pair * @param binStep The bin step of the LBPair * @return The LBPairInformation */ function _getLBPairInformation(IERC20 tokenA, IERC20 tokenB, uint256 binStep) private view returns (LBPairInformation memory) { (tokenA, tokenB) = _sortTokens(tokenA, tokenB); return _lbPairsInfo[tokenA][tokenB][binStep]; } /** * @notice Private view function to sort 2 tokens in ascending order * @param tokenA The first token * @param tokenB The second token * @return The sorted first token * @return The sorted second token */ function _sortTokens(IERC20 tokenA, IERC20 tokenB) private pure returns (IERC20, IERC20) { if (tokenA > tokenB) (tokenA, tokenB) = (tokenB, tokenA); return (tokenA, tokenB); } /** * @notice Internal function to set a hooks contract to the pair * @param tokenX The address of the first token * @param tokenY The address of the second token * @param binStep The bin step in basis point, used to calculate the price * @param hooksParameters The hooks parameters * @param onHooksSetData The data to pass to the onHooksSet function */ function _setLBHooksParametersOnPair( IERC20 tokenX, IERC20 tokenY, uint16 binStep, bytes32 hooksParameters, bytes memory onHooksSetData ) internal { ILBPair lbPair = _getLBPairInformation(tokenX, tokenY, binStep).LBPair; if (address(lbPair) == address(0)) revert LBFactory__LBPairNotCreated(tokenX, tokenY, binStep); if (lbPair.getLBHooksParameters() == hooksParameters) revert LBFactory__SameHooksParameters(hooksParameters); lbPair.setHooksParameters(hooksParameters, onHooksSetData); } /** * @notice Returns whether the caller has the role or not, only the owner has the DEFAULT_ADMIN_ROLE * @param role The role to check * @param account The address to check * @return Whether the account has the role or not */ function hasRole(bytes32 role, address account) public view override returns (bool) { if (role == DEFAULT_ADMIN_ROLE) return account == owner(); return super.hasRole(role, account); } /** * @notice Grants a role to an address, the DEFAULT_ADMIN_ROLE can not be granted * @param role The role to grant * @param account The address to grant the role to * @return Whether the role has been granted or not */ function _grantRole(bytes32 role, address account) internal override returns (bool) { if (role == DEFAULT_ADMIN_ROLE) revert LBFactory__CannotGrantDefaultAdminRole(); return super._grantRole(role, account); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.20; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position is the index of the value in the `values` array plus 1. // Position 0 is used to mean a value is not in the set. mapping(bytes32 value => uint256) _positions; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._positions[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We cache the value's position to prevent multiple reads from the same storage slot uint256 position = set._positions[value]; if (position != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 valueIndex = position - 1; uint256 lastIndex = set._values.length - 1; if (valueIndex != lastIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the lastValue to the index where the value to delete is set._values[valueIndex] = lastValue; // Update the tracked position of the lastValue (that was just moved) set._positions[lastValue] = position; } // Delete the slot where the moved value was stored set._values.pop(); // Delete the tracked position for the deleted slot delete set._positions[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._positions[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/EnumerableMap.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableMap.js. pragma solidity ^0.8.20; import {EnumerableSet} from "./EnumerableSet.sol"; /** * @dev Library for managing an enumerable variant of Solidity's * https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`] * type. * * Maps have the following properties: * * - Entries are added, removed, and checked for existence in constant time * (O(1)). * - Entries are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableMap for EnumerableMap.UintToAddressMap; * * // Declare a set state variable * EnumerableMap.UintToAddressMap private myMap; * } * ``` * * The following map types are supported: * * - `uint256 -> address` (`UintToAddressMap`) since v3.0.0 * - `address -> uint256` (`AddressToUintMap`) since v4.6.0 * - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0 * - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0 * - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0 * - `uint256 -> bytes32` (`UintToBytes32Map`) since v5.1.0 * - `address -> address` (`AddressToAddressMap`) since v5.1.0 * - `address -> bytes32` (`AddressToBytes32Map`) since v5.1.0 * - `bytes32 -> address` (`Bytes32ToAddressMap`) since v5.1.0 * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableMap. * ==== */ library EnumerableMap { using EnumerableSet for EnumerableSet.Bytes32Set; // To implement this library for multiple types with as little code repetition as possible, we write it in // terms of a generic Map type with bytes32 keys and values. The Map implementation uses private functions, // and user-facing implementations such as `UintToAddressMap` are just wrappers around the underlying Map. // This means that we can only create new EnumerableMaps for types that fit in bytes32. /** * @dev Query for a nonexistent map key. */ error EnumerableMapNonexistentKey(bytes32 key); struct Bytes32ToBytes32Map { // Storage of keys EnumerableSet.Bytes32Set _keys; mapping(bytes32 key => bytes32) _values; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) { map._values[key] = value; return map._keys.add(key); } /** * @dev Removes a key-value pair from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) { delete map._values[key]; return map._keys.remove(key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) { return map._keys.contains(key); } /** * @dev Returns the number of key-value pairs in the map. O(1). */ function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) { return map._keys.length(); } /** * @dev Returns the key-value pair stored at position `index` in the map. O(1). * * Note that there are no guarantees on the ordering of entries inside the * array, and it may change when more entries are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32, bytes32) { bytes32 key = map._keys.at(index); return (key, map._values[key]); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool, bytes32) { bytes32 value = map._values[key]; if (value == bytes32(0)) { return (contains(map, key), bytes32(0)); } else { return (true, value); } } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) { bytes32 value = map._values[key]; if (value == 0 && !contains(map, key)) { revert EnumerableMapNonexistentKey(key); } return value; } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) { return map._keys.values(); } // UintToUintMap struct UintToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToUintMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToUintMap storage map, uint256 index) internal view returns (uint256, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(key))); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(UintToUintMap storage map) internal view returns (uint256[] memory) { bytes32[] memory store = keys(map._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintToAddressMap struct UintToAddressMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) { return set(map._inner, bytes32(key), bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToAddressMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256, address) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), address(uint160(uint256(value)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool, address) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, address(uint160(uint256(value)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToAddressMap storage map, uint256 key) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(key))))); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) { bytes32[] memory store = keys(map._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintToBytes32Map struct UintToBytes32Map { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(UintToBytes32Map storage map, uint256 key, bytes32 value) internal returns (bool) { return set(map._inner, bytes32(key), value); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(UintToBytes32Map storage map, uint256 key) internal returns (bool) { return remove(map._inner, bytes32(key)); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(UintToBytes32Map storage map, uint256 key) internal view returns (bool) { return contains(map._inner, bytes32(key)); } /** * @dev Returns the number of elements in the map. O(1). */ function length(UintToBytes32Map storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintToBytes32Map storage map, uint256 index) internal view returns (uint256, bytes32) { (bytes32 key, bytes32 value) = at(map._inner, index); return (uint256(key), value); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(UintToBytes32Map storage map, uint256 key) internal view returns (bool, bytes32) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(key)); return (success, value); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(UintToBytes32Map storage map, uint256 key) internal view returns (bytes32) { return get(map._inner, bytes32(key)); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(UintToBytes32Map storage map) internal view returns (uint256[] memory) { bytes32[] memory store = keys(map._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressToUintMap struct AddressToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) { return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToUintMap storage map, address key) internal returns (bool) { return remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToUintMap storage map, address key) internal view returns (bool) { return contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressToUintMap storage map, uint256 index) internal view returns (address, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (address(uint160(uint256(key))), uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(AddressToUintMap storage map, address key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToUintMap storage map, address key) internal view returns (uint256) { return uint256(get(map._inner, bytes32(uint256(uint160(key))))); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(AddressToUintMap storage map) internal view returns (address[] memory) { bytes32[] memory store = keys(map._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressToAddressMap struct AddressToAddressMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(AddressToAddressMap storage map, address key, address value) internal returns (bool) { return set(map._inner, bytes32(uint256(uint160(key))), bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToAddressMap storage map, address key) internal returns (bool) { return remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToAddressMap storage map, address key) internal view returns (bool) { return contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToAddressMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressToAddressMap storage map, uint256 index) internal view returns (address, address) { (bytes32 key, bytes32 value) = at(map._inner, index); return (address(uint160(uint256(key))), address(uint160(uint256(value)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(AddressToAddressMap storage map, address key) internal view returns (bool, address) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, address(uint160(uint256(value)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToAddressMap storage map, address key) internal view returns (address) { return address(uint160(uint256(get(map._inner, bytes32(uint256(uint160(key))))))); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(AddressToAddressMap storage map) internal view returns (address[] memory) { bytes32[] memory store = keys(map._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressToBytes32Map struct AddressToBytes32Map { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(AddressToBytes32Map storage map, address key, bytes32 value) internal returns (bool) { return set(map._inner, bytes32(uint256(uint160(key))), value); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(AddressToBytes32Map storage map, address key) internal returns (bool) { return remove(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(AddressToBytes32Map storage map, address key) internal view returns (bool) { return contains(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Returns the number of elements in the map. O(1). */ function length(AddressToBytes32Map storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressToBytes32Map storage map, uint256 index) internal view returns (address, bytes32) { (bytes32 key, bytes32 value) = at(map._inner, index); return (address(uint160(uint256(key))), value); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(AddressToBytes32Map storage map, address key) internal view returns (bool, bytes32) { (bool success, bytes32 value) = tryGet(map._inner, bytes32(uint256(uint160(key)))); return (success, value); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(AddressToBytes32Map storage map, address key) internal view returns (bytes32) { return get(map._inner, bytes32(uint256(uint160(key)))); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(AddressToBytes32Map storage map) internal view returns (address[] memory) { bytes32[] memory store = keys(map._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // Bytes32ToUintMap struct Bytes32ToUintMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) { return set(map._inner, key, bytes32(value)); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) { return remove(map._inner, key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) { return contains(map._inner, key); } /** * @dev Returns the number of elements in the map. O(1). */ function length(Bytes32ToUintMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32, uint256) { (bytes32 key, bytes32 value) = at(map._inner, index); return (key, uint256(value)); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool, uint256) { (bool success, bytes32 value) = tryGet(map._inner, key); return (success, uint256(value)); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) { return uint256(get(map._inner, key)); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) { bytes32[] memory store = keys(map._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // Bytes32ToAddressMap struct Bytes32ToAddressMap { Bytes32ToBytes32Map _inner; } /** * @dev Adds a key-value pair to a map, or updates the value for an existing * key. O(1). * * Returns true if the key was added to the map, that is if it was not * already present. */ function set(Bytes32ToAddressMap storage map, bytes32 key, address value) internal returns (bool) { return set(map._inner, key, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a map. O(1). * * Returns true if the key was removed from the map, that is if it was present. */ function remove(Bytes32ToAddressMap storage map, bytes32 key) internal returns (bool) { return remove(map._inner, key); } /** * @dev Returns true if the key is in the map. O(1). */ function contains(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool) { return contains(map._inner, key); } /** * @dev Returns the number of elements in the map. O(1). */ function length(Bytes32ToAddressMap storage map) internal view returns (uint256) { return length(map._inner); } /** * @dev Returns the element stored at position `index` in the map. O(1). * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32ToAddressMap storage map, uint256 index) internal view returns (bytes32, address) { (bytes32 key, bytes32 value) = at(map._inner, index); return (key, address(uint160(uint256(value)))); } /** * @dev Tries to returns the value associated with `key`. O(1). * Does not revert if `key` is not in the map. */ function tryGet(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool, address) { (bool success, bytes32 value) = tryGet(map._inner, key); return (success, address(uint160(uint256(value)))); } /** * @dev Returns the value associated with `key`. O(1). * * Requirements: * * - `key` must be in the map. */ function get(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (address) { return address(uint160(uint256(get(map._inner, key)))); } /** * @dev Return the an array containing all the keys * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block. */ function keys(Bytes32ToAddressMap storage map) internal view returns (bytes32[] memory) { bytes32[] memory store = keys(map._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol) pragma solidity ^0.8.20; import {IAccessControl} from "./IAccessControl.sol"; import {Context} from "../utils/Context.sol"; import {ERC165} from "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address account => bool) hasRole; bytes32 adminRole; } mapping(bytes32 role => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with an {AccessControlUnauthorizedAccount} error including the required role. */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual returns (bool) { return _roles[role].hasRole[account]; } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()` * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier. */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account` * is missing `role`. */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert AccessControlUnauthorizedAccount(account, role); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address callerConfirmation) public virtual { if (callerConfirmation != _msgSender()) { revert AccessControlBadConfirmation(); } _revokeRole(role, callerConfirmation); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual returns (bool) { if (!hasRole(role, account)) { _roles[role].hasRole[account] = true; emit RoleGranted(role, account, _msgSender()); return true; } else { return false; } } /** * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual returns (bool) { if (hasRole(role, account)) { _roles[role].hasRole[account] = false; emit RoleRevoked(role, account, _msgSender()); return true; } else { return false; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ 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) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {Ownable} from "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * This extension of the {Ownable} contract includes a two-step mechanism to transfer * ownership, where the new owner must call {acceptOwnership} in order to replace the * old one. This can help prevent common mistakes, such as transfers of ownership to * incorrect accounts, or to contracts that are unable to interact with the * permission system. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {Constants} from "./Constants.sol"; import {SafeCast} from "./math/SafeCast.sol"; import {Encoded} from "./math/Encoded.sol"; /** * @title Liquidity Book Pair Parameter Helper Library * @author Trader Joe * @dev This library contains functions to get and set parameters of a pair * The parameters are stored in a single bytes32 variable in the following format: * [0 - 16[: base factor (16 bits) * [16 - 28[: filter period (12 bits) * [28 - 40[: decay period (12 bits) * [40 - 54[: reduction factor (14 bits) * [54 - 78[: variable fee control (24 bits) * [78 - 92[: protocol share (14 bits) * [92 - 112[: max volatility accumulator (20 bits) * [112 - 132[: volatility accumulator (20 bits) * [132 - 152[: volatility reference (20 bits) * [152 - 176[: index reference (24 bits) * [176 - 216[: time of last update (40 bits) * [216 - 232[: oracle index (16 bits) * [232 - 256[: active index (24 bits) */ library PairParameterHelper { using SafeCast for uint256; using Encoded for bytes32; error PairParametersHelper__InvalidParameter(); uint256 internal constant OFFSET_BASE_FACTOR = 0; uint256 internal constant OFFSET_FILTER_PERIOD = 16; uint256 internal constant OFFSET_DECAY_PERIOD = 28; uint256 internal constant OFFSET_REDUCTION_FACTOR = 40; uint256 internal constant OFFSET_VAR_FEE_CONTROL = 54; uint256 internal constant OFFSET_PROTOCOL_SHARE = 78; uint256 internal constant OFFSET_MAX_VOL_ACC = 92; uint256 internal constant OFFSET_VOL_ACC = 112; uint256 internal constant OFFSET_VOL_REF = 132; uint256 internal constant OFFSET_ID_REF = 152; uint256 internal constant OFFSET_TIME_LAST_UPDATE = 176; uint256 internal constant OFFSET_ORACLE_ID = 216; uint256 internal constant OFFSET_ACTIVE_ID = 232; uint256 internal constant MASK_STATIC_PARAMETER = 0xffffffffffffffffffffffffffff; /** * @dev Get the base factor from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 16[: base factor (16 bits) * [16 - 256[: other parameters * @return baseFactor The base factor */ function getBaseFactor(bytes32 params) internal pure returns (uint16 baseFactor) { baseFactor = params.decodeUint16(OFFSET_BASE_FACTOR); } /** * @dev Get the filter period from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 16[: other parameters * [16 - 28[: filter period (12 bits) * [28 - 256[: other parameters * @return filterPeriod The filter period */ function getFilterPeriod(bytes32 params) internal pure returns (uint16 filterPeriod) { filterPeriod = params.decodeUint12(OFFSET_FILTER_PERIOD); } /** * @dev Get the decay period from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 28[: other parameters * [28 - 40[: decay period (12 bits) * [40 - 256[: other parameters * @return decayPeriod The decay period */ function getDecayPeriod(bytes32 params) internal pure returns (uint16 decayPeriod) { decayPeriod = params.decodeUint12(OFFSET_DECAY_PERIOD); } /** * @dev Get the reduction factor from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 40[: other parameters * [40 - 54[: reduction factor (14 bits) * [54 - 256[: other parameters * @return reductionFactor The reduction factor */ function getReductionFactor(bytes32 params) internal pure returns (uint16 reductionFactor) { reductionFactor = params.decodeUint14(OFFSET_REDUCTION_FACTOR); } /** * @dev Get the variable fee control from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 54[: other parameters * [54 - 78[: variable fee control (24 bits) * [78 - 256[: other parameters * @return variableFeeControl The variable fee control */ function getVariableFeeControl(bytes32 params) internal pure returns (uint24 variableFeeControl) { variableFeeControl = params.decodeUint24(OFFSET_VAR_FEE_CONTROL); } /** * @dev Get the protocol share from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 78[: other parameters * [78 - 92[: protocol share (14 bits) * [92 - 256[: other parameters * @return protocolShare The protocol share */ function getProtocolShare(bytes32 params) internal pure returns (uint16 protocolShare) { protocolShare = params.decodeUint14(OFFSET_PROTOCOL_SHARE); } /** * @dev Get the max volatility accumulator from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 92[: other parameters * [92 - 112[: max volatility accumulator (20 bits) * [112 - 256[: other parameters * @return maxVolatilityAccumulator The max volatility accumulator */ function getMaxVolatilityAccumulator(bytes32 params) internal pure returns (uint24 maxVolatilityAccumulator) { maxVolatilityAccumulator = params.decodeUint20(OFFSET_MAX_VOL_ACC); } /** * @dev Get the volatility accumulator from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 112[: other parameters * [112 - 132[: volatility accumulator (20 bits) * [132 - 256[: other parameters * @return volatilityAccumulator The volatility accumulator */ function getVolatilityAccumulator(bytes32 params) internal pure returns (uint24 volatilityAccumulator) { volatilityAccumulator = params.decodeUint20(OFFSET_VOL_ACC); } /** * @dev Get the volatility reference from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 132[: other parameters * [132 - 152[: volatility reference (20 bits) * [152 - 256[: other parameters * @return volatilityReference The volatility reference */ function getVolatilityReference(bytes32 params) internal pure returns (uint24 volatilityReference) { volatilityReference = params.decodeUint20(OFFSET_VOL_REF); } /** * @dev Get the index reference from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 152[: other parameters * [152 - 176[: index reference (24 bits) * [176 - 256[: other parameters * @return idReference The index reference */ function getIdReference(bytes32 params) internal pure returns (uint24 idReference) { idReference = params.decodeUint24(OFFSET_ID_REF); } /** * @dev Get the time of last update from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 176[: other parameters * [176 - 216[: time of last update (40 bits) * [216 - 256[: other parameters * @return timeOflastUpdate The time of last update */ function getTimeOfLastUpdate(bytes32 params) internal pure returns (uint40 timeOflastUpdate) { timeOflastUpdate = params.decodeUint40(OFFSET_TIME_LAST_UPDATE); } /** * @dev Get the oracle id from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 216[: other parameters * [216 - 232[: oracle id (16 bits) * [232 - 256[: other parameters * @return oracleId The oracle id */ function getOracleId(bytes32 params) internal pure returns (uint16 oracleId) { oracleId = params.decodeUint16(OFFSET_ORACLE_ID); } /** * @dev Get the active index from the encoded pair parameters * @param params The encoded pair parameters, as follows: * [0 - 232[: other parameters * [232 - 256[: active index (24 bits) * @return activeId The active index */ function getActiveId(bytes32 params) internal pure returns (uint24 activeId) { activeId = params.decodeUint24(OFFSET_ACTIVE_ID); } /** * @dev Get the delta between the current active index and the cached active index * @param params The encoded pair parameters, as follows: * [0 - 232[: other parameters * [232 - 256[: active index (24 bits) * @param activeId The current active index * @return The delta */ function getDeltaId(bytes32 params, uint24 activeId) internal pure returns (uint24) { uint24 id = getActiveId(params); unchecked { return activeId > id ? activeId - id : id - activeId; } } /** * @dev Calculates the base fee, with 18 decimals * @param params The encoded pair parameters * @param binStep The bin step (in basis points) * @return baseFee The base fee */ function getBaseFee(bytes32 params, uint16 binStep) internal pure returns (uint256) { unchecked { // Base factor is in basis points, binStep is in basis points, so we multiply by 1e10 return uint256(getBaseFactor(params)) * binStep * 1e10; } } /** * @dev Calculates the variable fee * @param params The encoded pair parameters * @param binStep The bin step (in basis points) * @return variableFee The variable fee */ function getVariableFee(bytes32 params, uint16 binStep) internal pure returns (uint256 variableFee) { uint256 variableFeeControl = getVariableFeeControl(params); if (variableFeeControl != 0) { unchecked { // The volatility accumulator is in basis points, binStep is in basis points, // and the variable fee control is in basis points, so the result is in 100e18th uint256 prod = uint256(getVolatilityAccumulator(params)) * binStep; variableFee = (prod * prod * variableFeeControl + 99) / 100; } } } /** * @dev Calculates the total fee, which is the sum of the base fee and the variable fee * @param params The encoded pair parameters * @param binStep The bin step (in basis points) * @return totalFee The total fee */ function getTotalFee(bytes32 params, uint16 binStep) internal pure returns (uint128) { unchecked { return (getBaseFee(params, binStep) + getVariableFee(params, binStep)).safe128(); } } /** * @dev Set the oracle id in the encoded pair parameters * @param params The encoded pair parameters * @param oracleId The oracle id * @return The updated encoded pair parameters */ function setOracleId(bytes32 params, uint16 oracleId) internal pure returns (bytes32) { return params.set(oracleId, Encoded.MASK_UINT16, OFFSET_ORACLE_ID); } /** * @dev Set the volatility reference in the encoded pair parameters * @param params The encoded pair parameters * @param volRef The volatility reference * @return The updated encoded pair parameters */ function setVolatilityReference(bytes32 params, uint24 volRef) internal pure returns (bytes32) { if (volRef > Encoded.MASK_UINT20) revert PairParametersHelper__InvalidParameter(); return params.set(volRef, Encoded.MASK_UINT20, OFFSET_VOL_REF); } /** * @dev Set the volatility accumulator in the encoded pair parameters * @param params The encoded pair parameters * @param volAcc The volatility accumulator * @return The updated encoded pair parameters */ function setVolatilityAccumulator(bytes32 params, uint24 volAcc) internal pure returns (bytes32) { if (volAcc > Encoded.MASK_UINT20) revert PairParametersHelper__InvalidParameter(); return params.set(volAcc, Encoded.MASK_UINT20, OFFSET_VOL_ACC); } /** * @dev Set the active id in the encoded pair parameters * @param params The encoded pair parameters * @param activeId The active id * @return newParams The updated encoded pair parameters */ function setActiveId(bytes32 params, uint24 activeId) internal pure returns (bytes32 newParams) { return params.set(activeId, Encoded.MASK_UINT24, OFFSET_ACTIVE_ID); } /** * @dev Sets the static fee parameters in the encoded pair parameters * @param params The encoded pair parameters * @param baseFactor The base factor * @param filterPeriod The filter period * @param decayPeriod The decay period * @param reductionFactor The reduction factor * @param variableFeeControl The variable fee control * @param protocolShare The protocol share * @param maxVolatilityAccumulator The max volatility accumulator * @return newParams The updated encoded pair parameters */ function setStaticFeeParameters( bytes32 params, uint16 baseFactor, uint16 filterPeriod, uint16 decayPeriod, uint16 reductionFactor, uint24 variableFeeControl, uint16 protocolShare, uint24 maxVolatilityAccumulator ) internal pure returns (bytes32 newParams) { if ( filterPeriod > decayPeriod || decayPeriod > Encoded.MASK_UINT12 || reductionFactor > Constants.BASIS_POINT_MAX || protocolShare > Constants.MAX_PROTOCOL_SHARE || maxVolatilityAccumulator > Encoded.MASK_UINT20 ) revert PairParametersHelper__InvalidParameter(); newParams = newParams.set(baseFactor, Encoded.MASK_UINT16, OFFSET_BASE_FACTOR); newParams = newParams.set(filterPeriod, Encoded.MASK_UINT12, OFFSET_FILTER_PERIOD); newParams = newParams.set(decayPeriod, Encoded.MASK_UINT12, OFFSET_DECAY_PERIOD); newParams = newParams.set(reductionFactor, Encoded.MASK_UINT14, OFFSET_REDUCTION_FACTOR); newParams = newParams.set(variableFeeControl, Encoded.MASK_UINT24, OFFSET_VAR_FEE_CONTROL); newParams = newParams.set(protocolShare, Encoded.MASK_UINT14, OFFSET_PROTOCOL_SHARE); newParams = newParams.set(maxVolatilityAccumulator, Encoded.MASK_UINT20, OFFSET_MAX_VOL_ACC); return params.set(uint256(newParams), MASK_STATIC_PARAMETER, 0); } /** * @dev Updates the index reference in the encoded pair parameters * @param params The encoded pair parameters * @return newParams The updated encoded pair parameters */ function updateIdReference(bytes32 params) internal pure returns (bytes32 newParams) { uint24 activeId = getActiveId(params); return params.set(activeId, Encoded.MASK_UINT24, OFFSET_ID_REF); } /** * @dev Updates the time of last update in the encoded pair parameters * @param params The encoded pair parameters * @param timestamp The timestamp * @return newParams The updated encoded pair parameters */ function updateTimeOfLastUpdate(bytes32 params, uint256 timestamp) internal pure returns (bytes32 newParams) { uint40 currentTime = timestamp.safe40(); return params.set(currentTime, Encoded.MASK_UINT40, OFFSET_TIME_LAST_UPDATE); } /** * @dev Updates the volatility reference in the encoded pair parameters * @param params The encoded pair parameters * @return The updated encoded pair parameters */ function updateVolatilityReference(bytes32 params) internal pure returns (bytes32) { uint256 volAcc = getVolatilityAccumulator(params); uint256 reductionFactor = getReductionFactor(params); uint24 volRef; unchecked { volRef = uint24(volAcc * reductionFactor / Constants.BASIS_POINT_MAX); } return setVolatilityReference(params, volRef); } /** * @dev Updates the volatility accumulator in the encoded pair parameters * @param params The encoded pair parameters * @param activeId The active id * @return The updated encoded pair parameters */ function updateVolatilityAccumulator(bytes32 params, uint24 activeId) internal pure returns (bytes32) { uint256 idReference = getIdReference(params); uint256 deltaId; uint256 volAcc; unchecked { deltaId = activeId > idReference ? activeId - idReference : idReference - activeId; volAcc = (uint256(getVolatilityReference(params)) + deltaId * Constants.BASIS_POINT_MAX); } uint256 maxVolAcc = getMaxVolatilityAccumulator(params); volAcc = volAcc > maxVolAcc ? maxVolAcc : volAcc; return setVolatilityAccumulator(params, uint24(volAcc)); } /** * @dev Updates the volatility reference and the volatility accumulator in the encoded pair parameters * @param params The encoded pair parameters * @param timestamp The timestamp * @return The updated encoded pair parameters */ function updateReferences(bytes32 params, uint256 timestamp) internal pure returns (bytes32) { uint256 dt = timestamp - getTimeOfLastUpdate(params); if (dt >= getFilterPeriod(params)) { params = updateIdReference(params); params = dt < getDecayPeriod(params) ? updateVolatilityReference(params) : setVolatilityReference(params, 0); } return updateTimeOfLastUpdate(params, timestamp); } /** * @dev Updates the volatility reference and the volatility accumulator in the encoded pair parameters * @param params The encoded pair parameters * @param activeId The active id * @param timestamp The timestamp * @return The updated encoded pair parameters */ function updateVolatilityParameters(bytes32 params, uint24 activeId, uint256 timestamp) internal pure returns (bytes32) { params = updateReferences(params, timestamp); return updateVolatilityAccumulator(params, activeId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /** * @title Liquidity Book Encoded Library * @author Trader Joe * @notice Helper contract used for decoding bytes32 sample */ library Encoded { uint256 internal constant MASK_UINT1 = 0x1; uint256 internal constant MASK_UINT8 = 0xff; uint256 internal constant MASK_UINT12 = 0xfff; uint256 internal constant MASK_UINT14 = 0x3fff; uint256 internal constant MASK_UINT16 = 0xffff; uint256 internal constant MASK_UINT20 = 0xfffff; uint256 internal constant MASK_UINT24 = 0xffffff; uint256 internal constant MASK_UINT40 = 0xffffffffff; uint256 internal constant MASK_UINT64 = 0xffffffffffffffff; uint256 internal constant MASK_UINT128 = 0xffffffffffffffffffffffffffffffff; /** * @notice Internal function to set a value in an encoded bytes32 using a mask and offset * @dev This function can overflow * @param encoded The previous encoded value * @param value The value to encode * @param mask The mask * @param offset The offset * @return newEncoded The new encoded value */ function set(bytes32 encoded, uint256 value, uint256 mask, uint256 offset) internal pure returns (bytes32 newEncoded) { assembly { newEncoded := and(encoded, not(shl(offset, mask))) newEncoded := or(newEncoded, shl(offset, and(value, mask))) } } /** * @notice Internal function to set a bool in an encoded bytes32 using an offset * @dev This function can overflow * @param encoded The previous encoded value * @param boolean The bool to encode * @param offset The offset * @return newEncoded The new encoded value */ function setBool(bytes32 encoded, bool boolean, uint256 offset) internal pure returns (bytes32 newEncoded) { return set(encoded, boolean ? 1 : 0, MASK_UINT1, offset); } /** * @notice Internal function to decode a bytes32 sample using a mask and offset * @dev This function can overflow * @param encoded The encoded value * @param mask The mask * @param offset The offset * @return value The decoded value */ function decode(bytes32 encoded, uint256 mask, uint256 offset) internal pure returns (uint256 value) { assembly { value := and(shr(offset, encoded), mask) } } /** * @notice Internal function to decode a bytes32 sample into a bool using an offset * @dev This function can overflow * @param encoded The encoded value * @param offset The offset * @return boolean The decoded value as a bool */ function decodeBool(bytes32 encoded, uint256 offset) internal pure returns (bool boolean) { assembly { boolean := and(shr(offset, encoded), MASK_UINT1) } } /** * @notice Internal function to decode a bytes32 sample into a uint8 using an offset * @dev This function can overflow * @param encoded The encoded value * @param offset The offset * @return value The decoded value */ function decodeUint8(bytes32 encoded, uint256 offset) internal pure returns (uint8 value) { assembly { value := and(shr(offset, encoded), MASK_UINT8) } } /** * @notice Internal function to decode a bytes32 sample into a uint12 using an offset * @dev This function can overflow * @param encoded The encoded value * @param offset The offset * @return value The decoded value as a uint16, since uint12 is not supported */ function decodeUint12(bytes32 encoded, uint256 offset) internal pure returns (uint16 value) { assembly { value := and(shr(offset, encoded), MASK_UINT12) } } /** * @notice Internal function to decode a bytes32 sample into a uint14 using an offset * @dev This function can overflow * @param encoded The encoded value * @param offset The offset * @return value The decoded value as a uint16, since uint14 is not supported */ function decodeUint14(bytes32 encoded, uint256 offset) internal pure returns (uint16 value) { assembly { value := and(shr(offset, encoded), MASK_UINT14) } } /** * @notice Internal function to decode a bytes32 sample into a uint16 using an offset * @dev This function can overflow * @param encoded The encoded value * @param offset The offset * @return value The decoded value */ function decodeUint16(bytes32 encoded, uint256 offset) internal pure returns (uint16 value) { assembly { value := and(shr(offset, encoded), MASK_UINT16) } } /** * @notice Internal function to decode a bytes32 sample into a uint20 using an offset * @dev This function can overflow * @param encoded The encoded value * @param offset The offset * @return value The decoded value as a uint24, since uint20 is not supported */ function decodeUint20(bytes32 encoded, uint256 offset) internal pure returns (uint24 value) { assembly { value := and(shr(offset, encoded), MASK_UINT20) } } /** * @notice Internal function to decode a bytes32 sample into a uint24 using an offset * @dev This function can overflow * @param encoded The encoded value * @param offset The offset * @return value The decoded value */ function decodeUint24(bytes32 encoded, uint256 offset) internal pure returns (uint24 value) { assembly { value := and(shr(offset, encoded), MASK_UINT24) } } /** * @notice Internal function to decode a bytes32 sample into a uint40 using an offset * @dev This function can overflow * @param encoded The encoded value * @param offset The offset * @return value The decoded value */ function decodeUint40(bytes32 encoded, uint256 offset) internal pure returns (uint40 value) { assembly { value := and(shr(offset, encoded), MASK_UINT40) } } /** * @notice Internal function to decode a bytes32 sample into a uint64 using an offset * @dev This function can overflow * @param encoded The encoded value * @param offset The offset * @return value The decoded value */ function decodeUint64(bytes32 encoded, uint256 offset) internal pure returns (uint64 value) { assembly { value := and(shr(offset, encoded), MASK_UINT64) } } /** * @notice Internal function to decode a bytes32 sample into a uint128 using an offset * @dev This function can overflow * @param encoded The encoded value * @param offset The offset * @return value The decoded value */ function decodeUint128(bytes32 encoded, uint256 offset) internal pure returns (uint128 value) { assembly { value := and(shr(offset, encoded), MASK_UINT128) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /** * @title Liquidity Book Immutable Clone Library * @notice Minimal immutable proxy library. * @author Trader Joe * @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/LibClone.sol) * @author Minimal proxy by 0age (https://github.com/0age) * @author Clones with immutable args by wighawag, zefram.eth, Saw-mon & Natalie * (https://github.com/Saw-mon-and-Natalie/clones-with-immutable-args) * @dev Minimal proxy: * Although the sw0nt pattern saves 5 gas over the erc-1167 pattern during runtime, * it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern, * which saves 4 gas over the erc-1167 pattern during runtime, and has the smallest bytecode. * @dev Clones with immutable args (CWIA): * The implementation of CWIA here doesn't implements a `receive()` as it is not needed for LB. */ library ImmutableClone { error DeploymentFailed(); error PackedDataTooBig(); /** * @dev Deploys a deterministic clone of `implementation` using immutable arguments encoded in `data`, with `salt` * @param implementation The address of the implementation * @param data The encoded immutable arguments * @param salt The salt */ function cloneDeterministic(address implementation, bytes memory data, bytes32 salt) internal returns (address instance) { assembly { // Compute the boundaries of the data and cache the memory slots around it. let mBefore2 := mload(sub(data, 0x40)) let mBefore1 := mload(sub(data, 0x20)) let dataLength := mload(data) let dataEnd := add(add(data, 0x20), dataLength) let mAfter1 := mload(dataEnd) // +2 bytes for telling how much data there is appended to the call. let extraLength := add(dataLength, 2) // The `creationSize` is `extraLength + 63` // The `runSize` is `creationSize - 10`. // if `extraLength` is greater than `0xffca` revert as the `creationSize` would be greater than `0xffff`. if gt(extraLength, 0xffca) { // Store the function selector of `PackedDataTooBig()`. mstore(0x00, 0xc8c78139) // Revert with (offset, size). revert(0x1c, 0x04) } /** * ---------------------------------------------------------------------------------------------------+ * CREATION (10 bytes) | * ---------------------------------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * ---------------------------------------------------------------------------------------------------| * 61 runSize | PUSH2 runSize | r | | * 3d | RETURNDATASIZE | 0 r | | * 81 | DUP2 | r 0 r | | * 60 offset | PUSH1 offset | o r 0 r | | * 3d | RETURNDATASIZE | 0 o r 0 r | | * 39 | CODECOPY | 0 r | [0..runSize): runtime code | * f3 | RETURN | | [0..runSize): runtime code | * ---------------------------------------------------------------------------------------------------| * RUNTIME (98 bytes + extraLength) | * ---------------------------------------------------------------------------------------------------| * Opcode | Mnemonic | Stack | Memory | * ---------------------------------------------------------------------------------------------------| * | * ::: copy calldata to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds | | * 3d | RETURNDATASIZE | 0 cds | | * 3d | RETURNDATASIZE | 0 0 cds | | * 37 | CALLDATACOPY | | [0..cds): calldata | * | * ::: keep some values in stack :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | 0 | [0..cds): calldata | * 3d | RETURNDATASIZE | 0 0 | [0..cds): calldata | * 3d | RETURNDATASIZE | 0 0 0 | [0..cds): calldata | * 3d | RETURNDATASIZE | 0 0 0 0 | [0..cds): calldata | * 61 extra | PUSH2 extra | e 0 0 0 0 | [0..cds): calldata | * | * ::: copy extra data to memory :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 80 | DUP1 | e e 0 0 0 0 | [0..cds): calldata | * 60 0x35 | PUSH1 0x35 | 0x35 e e 0 0 0 0 | [0..cds): calldata | * 36 | CALLDATASIZE | cds 0x35 e e 0 0 0 0 | [0..cds): calldata | * 39 | CODECOPY | e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * | * ::: delegate call to the implementation contract ::::::::::::::::::::::::::::::::::::::::::::::::: | * 36 | CALLDATASIZE | cds e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 01 | ADD | cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 3d | RETURNDATASIZE | 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 73 addr | PUSH20 addr | addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 5a | GAS | gas addr 0 cds+e 0 0 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * f4 | DELEGATECALL | success 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * | * ::: copy return data to memory ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 3d | RETURNDATASIZE | rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 3d | RETURNDATASIZE | rds rds success 0 0 | [0..cds): calldata, [cds..cds+e): extraData | * 93 | SWAP4 | 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData | * 80 | DUP1 | 0 0 rds success 0 rds | [0..cds): calldata, [cds..cds+e): extraData | * 3e | RETURNDATACOPY | success 0 rds | [0..rds): returndata | * | * 60 0x33 | PUSH1 0x33 | 0x33 success 0 rds | [0..rds): returndata | * 57 | JUMPI | 0 rds | [0..rds): returndata | * | * ::: revert ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * fd | REVERT | | [0..rds): returndata | * | * ::: return ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: | * 5b | JUMPDEST | 0 rds | [0..rds): returndata | * f3 | RETURN | | [0..rds): returndata | * ---------------------------------------------------------------------------------------------------+ */ // Write the bytecode before the data. mstore(data, 0x5af43d3d93803e603357fd5bf3) // Write the address of the implementation. mstore(sub(data, 0x0d), implementation) mstore( sub(data, 0x21), or( shl(0xd8, add(extraLength, 0x35)), or(shl(0x48, extraLength), 0x6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d73) ) ) mstore(dataEnd, shl(0xf0, extraLength)) // Create the instance. instance := create2(0, sub(data, 0x1f), add(extraLength, 0x3f), salt) // If `instance` is zero, revert. if iszero(instance) { // Store the function selector of `DeploymentFailed()`. mstore(0x00, 0x30116425) // Revert with (offset, size). revert(0x1c, 0x04) } // Restore the overwritten memory surrounding `data`. mstore(dataEnd, mAfter1) mstore(data, dataLength) mstore(sub(data, 0x20), mBefore1) mstore(sub(data, 0x40), mBefore2) } } /** * @dev Returns the initialization code hash of the clone of `implementation` * using immutable arguments encoded in `data`. * Used for mining vanity addresses with create2crunch. * @param implementation The address of the implementation contract. * @param data The encoded immutable arguments. * @return hash The initialization code hash. */ function initCodeHash(address implementation, bytes memory data) internal pure returns (bytes32 hash) { assembly { // Compute the boundaries of the data and cache the memory slots around it. let mBefore2 := mload(sub(data, 0x40)) let mBefore1 := mload(sub(data, 0x20)) let dataLength := mload(data) let dataEnd := add(add(data, 0x20), dataLength) let mAfter1 := mload(dataEnd) // +2 bytes for telling how much data there is appended to the call. let extraLength := add(dataLength, 2) // The `creationSize` is `extraLength + 63` // The `runSize` is `creationSize - 10`. // if `extraLength` is greater than `0xffca` revert as the `creationSize` would be greater than `0xffff`. if gt(extraLength, 0xffca) { // Store the function selector of `PackedDataTooBig()`. mstore(0x00, 0xc8c78139) // Revert with (offset, size). revert(0x1c, 0x04) } // Write the bytecode before the data. mstore(data, 0x5af43d3d93803e603357fd5bf3) // Write the address of the implementation. mstore(sub(data, 0x0d), implementation) mstore( sub(data, 0x21), or( shl(0xd8, add(extraLength, 0x35)), or(shl(0x48, extraLength), 0x6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d73) ) ) mstore(dataEnd, shl(0xf0, extraLength)) // Create the instance. hash := keccak256(sub(data, 0x1f), add(extraLength, 0x3f)) // Restore the overwritten memory surrounding `data`. mstore(dataEnd, mAfter1) mstore(data, dataLength) mstore(sub(data, 0x20), mBefore1) mstore(sub(data, 0x40), mBefore2) } } /** * @dev Returns the address of the deterministic clone of * `implementation` using immutable arguments encoded in `data`, with `salt`, by `deployer`. * @param implementation The address of the implementation. * @param data The immutable arguments of the implementation. * @param salt The salt used to compute the address. * @param deployer The address of the deployer. * @return predicted The predicted address. */ function predictDeterministicAddress(address implementation, bytes memory data, bytes32 salt, address deployer) internal pure returns (address predicted) { bytes32 hash = initCodeHash(implementation, data); predicted = predictDeterministicAddress(hash, salt, deployer); } /** * @dev Returns the address when a contract with initialization code hash, * `hash`, is deployed with `salt`, by `deployer`. * @param hash The initialization code hash. * @param salt The salt used to compute the address. * @param deployer The address of the deployer. * @return predicted The predicted address. */ function predictDeterministicAddress(bytes32 hash, bytes32 salt, address deployer) internal pure returns (address predicted) { /// @solidity memory-safe-assembly assembly { // Compute the boundaries of the data and cache the memory slots around it. let mBefore := mload(0x35) // Compute and store the bytecode hash. mstore8(0x00, 0xff) // Write the prefix. mstore(0x35, hash) mstore(0x01, shl(96, deployer)) mstore(0x15, salt) predicted := keccak256(0x00, 0x55) // Restore the part of the free memory pointer that has been overwritten. mstore(0x35, mBefore) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {Uint128x128Math} from "./math/Uint128x128Math.sol"; import {Uint256x256Math} from "./math/Uint256x256Math.sol"; import {SafeCast} from "./math/SafeCast.sol"; import {Constants} from "./Constants.sol"; /** * @title Liquidity Book Price Helper Library * @author Trader Joe * @notice This library contains functions to calculate prices */ library PriceHelper { using Uint128x128Math for uint256; using Uint256x256Math for uint256; using SafeCast for uint256; int256 private constant REAL_ID_SHIFT = 1 << 23; /** * @dev Calculates the price from the id and the bin step * @param id The id * @param binStep The bin step * @return price The price as a 128.128-binary fixed-point number */ function getPriceFromId(uint24 id, uint16 binStep) internal pure returns (uint256 price) { uint256 base = getBase(binStep); int256 exponent = getExponent(id); price = base.pow(exponent); } /** * @dev Calculates the id from the price and the bin step * @param price The price as a 128.128-binary fixed-point number * @param binStep The bin step * @return id The id */ function getIdFromPrice(uint256 price, uint16 binStep) internal pure returns (uint24 id) { uint256 base = getBase(binStep); int256 realId = price.log2() / base.log2(); unchecked { id = uint256(REAL_ID_SHIFT + realId).safe24(); } } /** * @dev Calculates the base from the bin step, which is `1 + binStep / BASIS_POINT_MAX` * @param binStep The bin step * @return base The base */ function getBase(uint16 binStep) internal pure returns (uint256) { unchecked { return Constants.SCALE + (uint256(binStep) << Constants.SCALE_OFFSET) / Constants.BASIS_POINT_MAX; } } /** * @dev Calculates the exponent from the id, which is `id - REAL_ID_SHIFT` * @param id The id * @return exponent The exponent */ function getExponent(uint24 id) internal pure returns (int256) { unchecked { return int256(uint256(id)) - REAL_ID_SHIFT; } } /** * @dev Converts a price with 18 decimals to a 128.128-binary fixed-point number * @param price The price with 18 decimals * @return price128x128 The 128.128-binary fixed-point number */ function convertDecimalPriceTo128x128(uint256 price) internal pure returns (uint256) { return price.shiftDivRoundDown(Constants.SCALE_OFFSET, Constants.PRECISION); } /** * @dev Converts a 128.128-binary fixed-point number to a price with 18 decimals * @param price128x128 The 128.128-binary fixed-point number * @return price The price with 18 decimals */ function convert128x128PriceToDecimal(uint256 price128x128) internal pure returns (uint256) { return price128x128.mulShiftRoundDown(Constants.PRECISION, Constants.SCALE_OFFSET); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /** * @title Liquidity Book Safe Cast Library * @author Trader Joe * @notice This library contains functions to safely cast uint256 to different uint types. */ library SafeCast { error SafeCast__Exceeds248Bits(); error SafeCast__Exceeds240Bits(); error SafeCast__Exceeds232Bits(); error SafeCast__Exceeds224Bits(); error SafeCast__Exceeds216Bits(); error SafeCast__Exceeds208Bits(); error SafeCast__Exceeds200Bits(); error SafeCast__Exceeds192Bits(); error SafeCast__Exceeds184Bits(); error SafeCast__Exceeds176Bits(); error SafeCast__Exceeds168Bits(); error SafeCast__Exceeds160Bits(); error SafeCast__Exceeds152Bits(); error SafeCast__Exceeds144Bits(); error SafeCast__Exceeds136Bits(); error SafeCast__Exceeds128Bits(); error SafeCast__Exceeds120Bits(); error SafeCast__Exceeds112Bits(); error SafeCast__Exceeds104Bits(); error SafeCast__Exceeds96Bits(); error SafeCast__Exceeds88Bits(); error SafeCast__Exceeds80Bits(); error SafeCast__Exceeds72Bits(); error SafeCast__Exceeds64Bits(); error SafeCast__Exceeds56Bits(); error SafeCast__Exceeds48Bits(); error SafeCast__Exceeds40Bits(); error SafeCast__Exceeds32Bits(); error SafeCast__Exceeds24Bits(); error SafeCast__Exceeds16Bits(); error SafeCast__Exceeds8Bits(); /** * @dev Returns x on uint248 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint248 */ function safe248(uint256 x) internal pure returns (uint248 y) { if ((y = uint248(x)) != x) revert SafeCast__Exceeds248Bits(); } /** * @dev Returns x on uint240 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint240 */ function safe240(uint256 x) internal pure returns (uint240 y) { if ((y = uint240(x)) != x) revert SafeCast__Exceeds240Bits(); } /** * @dev Returns x on uint232 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint232 */ function safe232(uint256 x) internal pure returns (uint232 y) { if ((y = uint232(x)) != x) revert SafeCast__Exceeds232Bits(); } /** * @dev Returns x on uint224 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint224 */ function safe224(uint256 x) internal pure returns (uint224 y) { if ((y = uint224(x)) != x) revert SafeCast__Exceeds224Bits(); } /** * @dev Returns x on uint216 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint216 */ function safe216(uint256 x) internal pure returns (uint216 y) { if ((y = uint216(x)) != x) revert SafeCast__Exceeds216Bits(); } /** * @dev Returns x on uint208 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint208 */ function safe208(uint256 x) internal pure returns (uint208 y) { if ((y = uint208(x)) != x) revert SafeCast__Exceeds208Bits(); } /** * @dev Returns x on uint200 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint200 */ function safe200(uint256 x) internal pure returns (uint200 y) { if ((y = uint200(x)) != x) revert SafeCast__Exceeds200Bits(); } /** * @dev Returns x on uint192 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint192 */ function safe192(uint256 x) internal pure returns (uint192 y) { if ((y = uint192(x)) != x) revert SafeCast__Exceeds192Bits(); } /** * @dev Returns x on uint184 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint184 */ function safe184(uint256 x) internal pure returns (uint184 y) { if ((y = uint184(x)) != x) revert SafeCast__Exceeds184Bits(); } /** * @dev Returns x on uint176 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint176 */ function safe176(uint256 x) internal pure returns (uint176 y) { if ((y = uint176(x)) != x) revert SafeCast__Exceeds176Bits(); } /** * @dev Returns x on uint168 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint168 */ function safe168(uint256 x) internal pure returns (uint168 y) { if ((y = uint168(x)) != x) revert SafeCast__Exceeds168Bits(); } /** * @dev Returns x on uint160 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint160 */ function safe160(uint256 x) internal pure returns (uint160 y) { if ((y = uint160(x)) != x) revert SafeCast__Exceeds160Bits(); } /** * @dev Returns x on uint152 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint152 */ function safe152(uint256 x) internal pure returns (uint152 y) { if ((y = uint152(x)) != x) revert SafeCast__Exceeds152Bits(); } /** * @dev Returns x on uint144 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint144 */ function safe144(uint256 x) internal pure returns (uint144 y) { if ((y = uint144(x)) != x) revert SafeCast__Exceeds144Bits(); } /** * @dev Returns x on uint136 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint136 */ function safe136(uint256 x) internal pure returns (uint136 y) { if ((y = uint136(x)) != x) revert SafeCast__Exceeds136Bits(); } /** * @dev Returns x on uint128 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint128 */ function safe128(uint256 x) internal pure returns (uint128 y) { if ((y = uint128(x)) != x) revert SafeCast__Exceeds128Bits(); } /** * @dev Returns x on uint120 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint120 */ function safe120(uint256 x) internal pure returns (uint120 y) { if ((y = uint120(x)) != x) revert SafeCast__Exceeds120Bits(); } /** * @dev Returns x on uint112 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint112 */ function safe112(uint256 x) internal pure returns (uint112 y) { if ((y = uint112(x)) != x) revert SafeCast__Exceeds112Bits(); } /** * @dev Returns x on uint104 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint104 */ function safe104(uint256 x) internal pure returns (uint104 y) { if ((y = uint104(x)) != x) revert SafeCast__Exceeds104Bits(); } /** * @dev Returns x on uint96 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint96 */ function safe96(uint256 x) internal pure returns (uint96 y) { if ((y = uint96(x)) != x) revert SafeCast__Exceeds96Bits(); } /** * @dev Returns x on uint88 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint88 */ function safe88(uint256 x) internal pure returns (uint88 y) { if ((y = uint88(x)) != x) revert SafeCast__Exceeds88Bits(); } /** * @dev Returns x on uint80 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint80 */ function safe80(uint256 x) internal pure returns (uint80 y) { if ((y = uint80(x)) != x) revert SafeCast__Exceeds80Bits(); } /** * @dev Returns x on uint72 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint72 */ function safe72(uint256 x) internal pure returns (uint72 y) { if ((y = uint72(x)) != x) revert SafeCast__Exceeds72Bits(); } /** * @dev Returns x on uint64 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint64 */ function safe64(uint256 x) internal pure returns (uint64 y) { if ((y = uint64(x)) != x) revert SafeCast__Exceeds64Bits(); } /** * @dev Returns x on uint56 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint56 */ function safe56(uint256 x) internal pure returns (uint56 y) { if ((y = uint56(x)) != x) revert SafeCast__Exceeds56Bits(); } /** * @dev Returns x on uint48 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint48 */ function safe48(uint256 x) internal pure returns (uint48 y) { if ((y = uint48(x)) != x) revert SafeCast__Exceeds48Bits(); } /** * @dev Returns x on uint40 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint40 */ function safe40(uint256 x) internal pure returns (uint40 y) { if ((y = uint40(x)) != x) revert SafeCast__Exceeds40Bits(); } /** * @dev Returns x on uint32 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint32 */ function safe32(uint256 x) internal pure returns (uint32 y) { if ((y = uint32(x)) != x) revert SafeCast__Exceeds32Bits(); } /** * @dev Returns x on uint24 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint24 */ function safe24(uint256 x) internal pure returns (uint24 y) { if ((y = uint24(x)) != x) revert SafeCast__Exceeds24Bits(); } /** * @dev Returns x on uint16 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint16 */ function safe16(uint256 x) internal pure returns (uint16 y) { if ((y = uint16(x)) != x) revert SafeCast__Exceeds16Bits(); } /** * @dev Returns x on uint8 and check that it does not overflow * @param x The value as an uint256 * @return y The value as an uint8 */ function safe8(uint256 x) internal pure returns (uint8 y) { if ((y = uint8(x)) != x) revert SafeCast__Exceeds8Bits(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {ILBHooks} from "../interfaces/ILBHooks.sol"; /** * @title Hooks library * @notice This library contains functions that should be used to interact with hooks */ library Hooks { error Hooks__CallFailed(); bytes32 internal constant BEFORE_SWAP_FLAG = bytes32(uint256(1 << 160)); bytes32 internal constant AFTER_SWAP_FLAG = bytes32(uint256(1 << 161)); bytes32 internal constant BEFORE_FLASH_LOAN_FLAG = bytes32(uint256(1 << 162)); bytes32 internal constant AFTER_FLASH_LOAN_FLAG = bytes32(uint256(1 << 163)); bytes32 internal constant BEFORE_MINT_FLAG = bytes32(uint256(1 << 164)); bytes32 internal constant AFTER_MINT_FLAG = bytes32(uint256(1 << 165)); bytes32 internal constant BEFORE_BURN_FLAG = bytes32(uint256(1 << 166)); bytes32 internal constant AFTER_BURN_FLAG = bytes32(uint256(1 << 167)); bytes32 internal constant BEFORE_TRANSFER_FLAG = bytes32(uint256(1 << 168)); bytes32 internal constant AFTER_TRANSFER_FLAG = bytes32(uint256(1 << 169)); struct Parameters { address hooks; bool beforeSwap; bool afterSwap; bool beforeFlashLoan; bool afterFlashLoan; bool beforeMint; bool afterMint; bool beforeBurn; bool afterBurn; bool beforeBatchTransferFrom; bool afterBatchTransferFrom; } /** * @dev Helper function to encode the hooks parameters to a single bytes32 value * @param parameters The hooks parameters * @return hooksParameters The encoded hooks parameters */ function encode(Parameters memory parameters) internal pure returns (bytes32 hooksParameters) { hooksParameters = bytes32(uint256(uint160(address(parameters.hooks)))); if (parameters.beforeSwap) hooksParameters |= BEFORE_SWAP_FLAG; if (parameters.afterSwap) hooksParameters |= AFTER_SWAP_FLAG; if (parameters.beforeFlashLoan) hooksParameters |= BEFORE_FLASH_LOAN_FLAG; if (parameters.afterFlashLoan) hooksParameters |= AFTER_FLASH_LOAN_FLAG; if (parameters.beforeMint) hooksParameters |= BEFORE_MINT_FLAG; if (parameters.afterMint) hooksParameters |= AFTER_MINT_FLAG; if (parameters.beforeBurn) hooksParameters |= BEFORE_BURN_FLAG; if (parameters.afterBurn) hooksParameters |= AFTER_BURN_FLAG; if (parameters.beforeBatchTransferFrom) hooksParameters |= BEFORE_TRANSFER_FLAG; if (parameters.afterBatchTransferFrom) hooksParameters |= AFTER_TRANSFER_FLAG; } /** * @dev Helper function to decode the hooks parameters from a single bytes32 value * @param hooksParameters The encoded hooks parameters * @return parameters The hooks parameters */ function decode(bytes32 hooksParameters) internal pure returns (Parameters memory parameters) { parameters.hooks = getHooks(hooksParameters); parameters.beforeSwap = (hooksParameters & BEFORE_SWAP_FLAG) != 0; parameters.afterSwap = (hooksParameters & AFTER_SWAP_FLAG) != 0; parameters.beforeFlashLoan = (hooksParameters & BEFORE_FLASH_LOAN_FLAG) != 0; parameters.afterFlashLoan = (hooksParameters & AFTER_FLASH_LOAN_FLAG) != 0; parameters.beforeMint = (hooksParameters & BEFORE_MINT_FLAG) != 0; parameters.afterMint = (hooksParameters & AFTER_MINT_FLAG) != 0; parameters.beforeBurn = (hooksParameters & BEFORE_BURN_FLAG) != 0; parameters.afterBurn = (hooksParameters & AFTER_BURN_FLAG) != 0; parameters.beforeBatchTransferFrom = (hooksParameters & BEFORE_TRANSFER_FLAG) != 0; parameters.afterBatchTransferFrom = (hooksParameters & AFTER_TRANSFER_FLAG) != 0; } /** * @dev Helper function to get the hooks address from the encoded hooks parameters * @param hooksParameters The encoded hooks parameters * @return hooks The hooks address */ function getHooks(bytes32 hooksParameters) internal pure returns (address hooks) { hooks = address(uint160(uint256(hooksParameters))); } /** * @dev Helper function to set the hooks address in the encoded hooks parameters * @param hooksParameters The encoded hooks parameters * @param newHooks The new hooks address * @return hooksParameters The updated hooks parameters */ function setHooks(bytes32 hooksParameters, address newHooks) internal pure returns (bytes32) { return bytes32(bytes12(hooksParameters)) | bytes32(uint256(uint160(newHooks))); } /** * @dev Helper function to get the flags from the encoded hooks parameters * @param hooksParameters The encoded hooks parameters * @return flags The flags */ function getFlags(bytes32 hooksParameters) internal pure returns (bytes12 flags) { flags = bytes12(hooksParameters); } /** * @dev Helper function call the onHooksSet function on the hooks contract, only if the * hooksParameters is not 0 * @param hooksParameters The encoded hooks parameters * @param onHooksSetData The data to pass to the onHooksSet function */ function onHooksSet(bytes32 hooksParameters, bytes calldata onHooksSetData) internal { if (hooksParameters != 0) { _safeCall( hooksParameters, abi.encodeWithSelector(ILBHooks.onHooksSet.selector, hooksParameters, onHooksSetData) ); } } /** * @dev Helper function to call the beforeSwap function on the hooks contract, only if the * BEFORE_SWAP_FLAG is set in the hooksParameters * @param hooksParameters The encoded hooks parameters * @param sender The sender * @param to The recipient * @param swapForY Whether the swap is for Y * @param amountsIn The amounts in */ function beforeSwap(bytes32 hooksParameters, address sender, address to, bool swapForY, bytes32 amountsIn) internal { if ((hooksParameters & BEFORE_SWAP_FLAG) != 0) { _safeCall( hooksParameters, abi.encodeWithSelector(ILBHooks.beforeSwap.selector, sender, to, swapForY, amountsIn) ); } } /** * @dev Helper function to call the afterSwap function on the hooks contract, only if the * AFTER_SWAP_FLAG is set in the hooksParameters * @param hooksParameters The encoded hooks parameters * @param sender The sender * @param to The recipient * @param swapForY Whether the swap is for Y * @param amountsOut The amounts out */ function afterSwap(bytes32 hooksParameters, address sender, address to, bool swapForY, bytes32 amountsOut) internal { if ((hooksParameters & AFTER_SWAP_FLAG) != 0) { _safeCall( hooksParameters, abi.encodeWithSelector(ILBHooks.afterSwap.selector, sender, to, swapForY, amountsOut) ); } } /** * @dev Helper function to call the beforeFlashLoan function on the hooks contract, only if the * BEFORE_FLASH_LOAN_FLAG is set in the hooksParameters * @param hooksParameters The encoded hooks parameters * @param sender The sender * @param to The recipient * @param amounts The amounts */ function beforeFlashLoan(bytes32 hooksParameters, address sender, address to, bytes32 amounts) internal { if ((hooksParameters & BEFORE_FLASH_LOAN_FLAG) != 0) { _safeCall(hooksParameters, abi.encodeWithSelector(ILBHooks.beforeFlashLoan.selector, sender, to, amounts)); } } /** * @dev Helper function to call the afterFlashLoan function on the hooks contract, only if the * AFTER_FLASH_LOAN_FLAG is set in the hooksParameters * @param hooksParameters The encoded hooks parameters * @param sender The sender * @param to The recipient * @param fees The fees * @param feesReceived The fees received */ function afterFlashLoan(bytes32 hooksParameters, address sender, address to, bytes32 fees, bytes32 feesReceived) internal { if ((hooksParameters & AFTER_FLASH_LOAN_FLAG) != 0) { _safeCall( hooksParameters, abi.encodeWithSelector(ILBHooks.afterFlashLoan.selector, sender, to, fees, feesReceived) ); } } /** * @dev Helper function to call the beforeMint function on the hooks contract, only if the * BEFORE_MINT_FLAG is set in the hooksParameters * @param hooksParameters The encoded hooks parameters * @param sender The sender * @param to The recipient * @param liquidityConfigs The liquidity configs * @param amountsReceived The amounts received */ function beforeMint( bytes32 hooksParameters, address sender, address to, bytes32[] calldata liquidityConfigs, bytes32 amountsReceived ) internal { if ((hooksParameters & BEFORE_MINT_FLAG) != 0) { _safeCall( hooksParameters, abi.encodeWithSelector(ILBHooks.beforeMint.selector, sender, to, liquidityConfigs, amountsReceived) ); } } /** * @dev Helper function to call the afterMint function on the hooks contract, only if the * AFTER_MINT_FLAG is set in the hooksParameters * @param hooksParameters The encoded hooks parameters * @param sender The sender * @param to The recipient * @param liquidityConfigs The liquidity configs * @param amountsIn The amounts in */ function afterMint( bytes32 hooksParameters, address sender, address to, bytes32[] calldata liquidityConfigs, bytes32 amountsIn ) internal { if ((hooksParameters & AFTER_MINT_FLAG) != 0) { _safeCall( hooksParameters, abi.encodeWithSelector(ILBHooks.afterMint.selector, sender, to, liquidityConfigs, amountsIn) ); } } /** * @dev Helper function to call the beforeBurn function on the hooks contract, only if the * BEFORE_BURN_FLAG is set in the hooksParameters * @param hooksParameters The encoded hooks parameters * @param sender The sender * @param from The sender * @param to The recipient * @param ids The ids * @param amountsToBurn The amounts to burn */ function beforeBurn( bytes32 hooksParameters, address sender, address from, address to, uint256[] calldata ids, uint256[] calldata amountsToBurn ) internal { if ((hooksParameters & BEFORE_BURN_FLAG) != 0) { _safeCall( hooksParameters, abi.encodeWithSelector(ILBHooks.beforeBurn.selector, sender, from, to, ids, amountsToBurn) ); } } /** * @dev Helper function to call the afterBurn function on the hooks contract, only if the * AFTER_BURN_FLAG is set in the hooksParameters * @param hooksParameters The encoded hooks parameters * @param sender The sender * @param from The sender * @param to The recipient * @param ids The ids * @param amountsToBurn The amounts to burn */ function afterBurn( bytes32 hooksParameters, address sender, address from, address to, uint256[] calldata ids, uint256[] calldata amountsToBurn ) internal { if ((hooksParameters & AFTER_BURN_FLAG) != 0) { _safeCall( hooksParameters, abi.encodeWithSelector(ILBHooks.afterBurn.selector, sender, from, to, ids, amountsToBurn) ); } } /** * @dev Helper function to call the beforeTransferFrom function on the hooks contract, only if the * BEFORE_TRANSFER_FLAG is set in the hooksParameters * @param hooksParameters The encoded hooks parameters * @param sender The sender * @param from The sender * @param to The recipient * @param ids The list of ids * @param amounts The list of amounts */ function beforeBatchTransferFrom( bytes32 hooksParameters, address sender, address from, address to, uint256[] calldata ids, uint256[] calldata amounts ) internal { if ((hooksParameters & BEFORE_TRANSFER_FLAG) != 0) { _safeCall( hooksParameters, abi.encodeWithSelector(ILBHooks.beforeBatchTransferFrom.selector, sender, from, to, ids, amounts) ); } } /** * @dev Helper function to call the afterTransferFrom function on the hooks contract, only if the * AFTER_TRANSFER_FLAG is set in the hooksParameters * @param hooksParameters The encoded hooks parameters * @param sender The sender * @param from The sender * @param to The recipient * @param ids The list of ids * @param amounts The list of amounts */ function afterBatchTransferFrom( bytes32 hooksParameters, address sender, address from, address to, uint256[] calldata ids, uint256[] calldata amounts ) internal { if ((hooksParameters & AFTER_TRANSFER_FLAG) != 0) { _safeCall( hooksParameters, abi.encodeWithSelector(ILBHooks.afterBatchTransferFrom.selector, sender, from, to, ids, amounts) ); } } /** * @dev Helper function to call the hooks contract and verify the call was successful * by matching the expected selector with the returned data * @param hooksParameters The encoded hooks parameters * @param data The data to pass to the hooks contract */ function _safeCall(bytes32 hooksParameters, bytes memory data) private { bool success; address hooks = getHooks(hooksParameters); assembly { let expectedSelector := shr(224, mload(add(data, 0x20))) success := call(gas(), hooks, 0, add(data, 0x20), mload(data), 0, 0x20) if and(iszero(success), iszero(iszero(returndatasize()))) { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } success := and(success, and(gt(returndatasize(), 0x1f), eq(shr(224, mload(0)), expectedSelector))) } if (!success) revert Hooks__CallFailed(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {ILBHooks} from "./ILBHooks.sol"; import {ILBPair} from "./ILBPair.sol"; /** * @title Liquidity Book Factory Interface * @author Trader Joe * @notice Required interface of LBFactory contract */ interface ILBFactory { error LBFactory__IdenticalAddresses(IERC20 token); error LBFactory__QuoteAssetNotWhitelisted(IERC20 quoteAsset); error LBFactory__QuoteAssetAlreadyWhitelisted(IERC20 quoteAsset); error LBFactory__AddressZero(); error LBFactory__LBPairAlreadyExists(IERC20 tokenX, IERC20 tokenY, uint256 _binStep); error LBFactory__LBPairDoesNotExist(IERC20 tokenX, IERC20 tokenY, uint256 binStep); error LBFactory__LBPairNotCreated(IERC20 tokenX, IERC20 tokenY, uint256 binStep); error LBFactory__FlashLoanFeeAboveMax(uint256 fees, uint256 maxFees); error LBFactory__BinStepTooLow(uint256 binStep); error LBFactory__PresetIsLockedForUsers(address user, uint256 binStep); error LBFactory__LBPairIgnoredIsAlreadyInTheSameState(); error LBFactory__BinStepHasNoPreset(uint256 binStep); error LBFactory__PresetOpenStateIsAlreadyInTheSameState(); error LBFactory__SameFeeRecipient(address feeRecipient); error LBFactory__SameFlashLoanFee(uint256 flashLoanFee); error LBFactory__LBPairSafetyCheckFailed(address LBPairImplementation); error LBFactory__SameImplementation(address LBPairImplementation); error LBFactory__ImplementationNotSet(); error LBFactory__SameHooksImplementation(address hooksImplementation); error LBFactory__SameHooksParameters(bytes32 hooksParameters); error LBFactory__InvalidHooksParameters(); error LBFactory__CannotGrantDefaultAdminRole(); /** * @dev Structure to store the LBPair information, such as: * binStep: The bin step of the LBPair * LBPair: The address of the LBPair * createdByOwner: Whether the pair was created by the owner of the factory * ignoredForRouting: Whether the pair is ignored for routing or not. An ignored pair will not be explored during routes finding */ struct LBPairInformation { uint16 binStep; ILBPair LBPair; bool createdByOwner; bool ignoredForRouting; } event LBPairCreated( IERC20 indexed tokenX, IERC20 indexed tokenY, uint256 indexed binStep, ILBPair LBPair, uint256 pid ); event FeeRecipientSet(address oldRecipient, address newRecipient); event FlashLoanFeeSet(uint256 oldFlashLoanFee, uint256 newFlashLoanFee); event LBPairImplementationSet(address oldLBPairImplementation, address LBPairImplementation); event LBPairIgnoredStateChanged(ILBPair indexed LBPair, bool ignored); event PresetSet( uint256 indexed binStep, uint256 baseFactor, uint256 filterPeriod, uint256 decayPeriod, uint256 reductionFactor, uint256 variableFeeControl, uint256 protocolShare, uint256 maxVolatilityAccumulator ); event PresetOpenStateChanged(uint256 indexed binStep, bool indexed isOpen); event PresetRemoved(uint256 indexed binStep); event QuoteAssetAdded(IERC20 indexed quoteAsset); event QuoteAssetRemoved(IERC20 indexed quoteAsset); function getMinBinStep() external pure returns (uint256); function getFeeRecipient() external view returns (address); function getMaxFlashLoanFee() external pure returns (uint256); function getFlashLoanFee() external view returns (uint256); function getLBPairImplementation() external view returns (address); function getNumberOfLBPairs() external view returns (uint256); function getLBPairAtIndex(uint256 id) external returns (ILBPair); function getNumberOfQuoteAssets() external view returns (uint256); function getQuoteAssetAtIndex(uint256 index) external view returns (IERC20); function isQuoteAsset(IERC20 token) external view returns (bool); function getLBPairInformation(IERC20 tokenX, IERC20 tokenY, uint256 binStep) external view returns (LBPairInformation memory); function getPreset(uint256 binStep) external view returns ( uint256 baseFactor, uint256 filterPeriod, uint256 decayPeriod, uint256 reductionFactor, uint256 variableFeeControl, uint256 protocolShare, uint256 maxAccumulator, bool isOpen ); function getAllBinSteps() external view returns (uint256[] memory presetsBinStep); function getOpenBinSteps() external view returns (uint256[] memory openBinStep); function getAllLBPairs(IERC20 tokenX, IERC20 tokenY) external view returns (LBPairInformation[] memory LBPairsBinStep); function setLBPairImplementation(address lbPairImplementation) external; function createLBPair(IERC20 tokenX, IERC20 tokenY, uint24 activeId, uint16 binStep) external returns (ILBPair pair); function setLBPairIgnored(IERC20 tokenX, IERC20 tokenY, uint16 binStep, bool ignored) external; function setPreset( uint16 binStep, uint16 baseFactor, uint16 filterPeriod, uint16 decayPeriod, uint16 reductionFactor, uint24 variableFeeControl, uint16 protocolShare, uint24 maxVolatilityAccumulator, bool isOpen ) external; function setPresetOpenState(uint16 binStep, bool isOpen) external; function removePreset(uint16 binStep) external; function setFeesParametersOnPair( IERC20 tokenX, IERC20 tokenY, uint16 binStep, uint16 baseFactor, uint16 filterPeriod, uint16 decayPeriod, uint16 reductionFactor, uint24 variableFeeControl, uint16 protocolShare, uint24 maxVolatilityAccumulator ) external; function setLBHooksParametersOnPair( IERC20 tokenX, IERC20 tokenY, uint16 binStep, bytes32 hooksParameters, bytes memory onHooksSetData ) external; function removeLBHooksOnPair(IERC20 tokenX, IERC20 tokenY, uint16 binStep) external; function setFeeRecipient(address feeRecipient) external; function setFlashLoanFee(uint256 flashLoanFee) external; function addQuoteAsset(IERC20 quoteAsset) external; function removeQuoteAsset(IERC20 quoteAsset) external; function forceDecay(ILBPair lbPair) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Hooks} from "../libraries/Hooks.sol"; import {ILBFactory} from "./ILBFactory.sol"; import {ILBFlashLoanCallback} from "./ILBFlashLoanCallback.sol"; import {ILBToken} from "./ILBToken.sol"; interface ILBPair is ILBToken { error LBPair__ZeroBorrowAmount(); error LBPair__AddressZero(); error LBPair__EmptyMarketConfigs(); error LBPair__FlashLoanCallbackFailed(); error LBPair__FlashLoanInsufficientAmount(); error LBPair__InsufficientAmountIn(); error LBPair__InsufficientAmountOut(); error LBPair__InvalidInput(); error LBPair__InvalidStaticFeeParameters(); error LBPair__OnlyFactory(); error LBPair__OnlyProtocolFeeRecipient(); error LBPair__OutOfLiquidity(); error LBPair__TokenNotSupported(); error LBPair__ZeroAmount(uint24 id); error LBPair__ZeroAmountsOut(uint24 id); error LBPair__ZeroShares(uint24 id); error LBPair__MaxTotalFeeExceeded(); error LBPair__InvalidHooks(); struct MintArrays { uint256[] ids; bytes32[] amounts; uint256[] liquidityMinted; } event DepositedToBins(address indexed sender, address indexed to, uint256[] ids, bytes32[] amounts); event WithdrawnFromBins(address indexed sender, address indexed to, uint256[] ids, bytes32[] amounts); event CompositionFees(address indexed sender, uint24 id, bytes32 totalFees, bytes32 protocolFees); event CollectedProtocolFees(address indexed feeRecipient, bytes32 protocolFees); event Swap( address indexed sender, address indexed to, uint24 id, bytes32 amountsIn, bytes32 amountsOut, uint24 volatilityAccumulator, bytes32 totalFees, bytes32 protocolFees ); event StaticFeeParametersSet( address indexed sender, uint16 baseFactor, uint16 filterPeriod, uint16 decayPeriod, uint16 reductionFactor, uint24 variableFeeControl, uint16 protocolShare, uint24 maxVolatilityAccumulator ); event HooksParametersSet(address indexed sender, bytes32 hooksParameters); event FlashLoan( address indexed sender, ILBFlashLoanCallback indexed receiver, uint24 activeId, bytes32 amounts, bytes32 totalFees, bytes32 protocolFees ); event OracleLengthIncreased(address indexed sender, uint16 oracleLength); event ForcedDecay(address indexed sender, uint24 idReference, uint24 volatilityReference); function initialize( uint16 baseFactor, uint16 filterPeriod, uint16 decayPeriod, uint16 reductionFactor, uint24 variableFeeControl, uint16 protocolShare, uint24 maxVolatilityAccumulator, uint24 activeId ) external; function implementation() external view returns (address); function getFactory() external view returns (ILBFactory factory); function getTokenX() external view returns (IERC20 tokenX); function getTokenY() external view returns (IERC20 tokenY); function getBinStep() external view returns (uint16 binStep); function getReserves() external view returns (uint128 reserveX, uint128 reserveY); function getActiveId() external view returns (uint24 activeId); function getBin(uint24 id) external view returns (uint128 binReserveX, uint128 binReserveY); function getNextNonEmptyBin(bool swapForY, uint24 id) external view returns (uint24 nextId); function getProtocolFees() external view returns (uint128 protocolFeeX, uint128 protocolFeeY); function getStaticFeeParameters() external view returns ( uint16 baseFactor, uint16 filterPeriod, uint16 decayPeriod, uint16 reductionFactor, uint24 variableFeeControl, uint16 protocolShare, uint24 maxVolatilityAccumulator ); function getLBHooksParameters() external view returns (bytes32 hooksParameters); function getVariableFeeParameters() external view returns (uint24 volatilityAccumulator, uint24 volatilityReference, uint24 idReference, uint40 timeOfLastUpdate); function getOracleParameters() external view returns (uint8 sampleLifetime, uint16 size, uint16 activeSize, uint40 lastUpdated, uint40 firstTimestamp); function getOracleSampleAt(uint40 lookupTimestamp) external view returns (uint64 cumulativeId, uint64 cumulativeVolatility, uint64 cumulativeBinCrossed); function getPriceFromId(uint24 id) external view returns (uint256 price); function getIdFromPrice(uint256 price) external view returns (uint24 id); function getSwapIn(uint128 amountOut, bool swapForY) external view returns (uint128 amountIn, uint128 amountOutLeft, uint128 fee); function getSwapOut(uint128 amountIn, bool swapForY) external view returns (uint128 amountInLeft, uint128 amountOut, uint128 fee); function swap(bool swapForY, address to) external returns (bytes32 amountsOut); function flashLoan(ILBFlashLoanCallback receiver, bytes32 amounts, bytes calldata data) external; function mint(address to, bytes32[] calldata liquidityConfigs, address refundTo) external returns (bytes32 amountsReceived, bytes32 amountsLeft, uint256[] memory liquidityMinted); function burn(address from, address to, uint256[] calldata ids, uint256[] calldata amountsToBurn) external returns (bytes32[] memory amounts); function collectProtocolFees() external returns (bytes32 collectedProtocolFees); function increaseOracleLength(uint16 newLength) external; function setStaticFeeParameters( uint16 baseFactor, uint16 filterPeriod, uint16 decayPeriod, uint16 reductionFactor, uint24 variableFeeControl, uint16 protocolShare, uint24 maxVolatilityAccumulator ) external; function setHooksParameters(bytes32 hooksParameters, bytes calldata onHooksSetData) external; function forceDecay() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {ILBPair} from "./ILBPair.sol"; import {Hooks} from "../libraries/Hooks.sol"; interface ILBHooks { function getLBPair() external view returns (ILBPair); function isLinked() external view returns (bool); function onHooksSet(bytes32 hooksParameters, bytes calldata onHooksSetData) external returns (bytes4); function beforeSwap(address sender, address to, bool swapForY, bytes32 amountsIn) external returns (bytes4); function afterSwap(address sender, address to, bool swapForY, bytes32 amountsOut) external returns (bytes4); function beforeFlashLoan(address sender, address to, bytes32 amounts) external returns (bytes4); function afterFlashLoan(address sender, address to, bytes32 fees, bytes32 feesReceived) external returns (bytes4); function beforeMint(address sender, address to, bytes32[] calldata liquidityConfigs, bytes32 amountsReceived) external returns (bytes4); function afterMint(address sender, address to, bytes32[] calldata liquidityConfigs, bytes32 amountsIn) external returns (bytes4); function beforeBurn( address sender, address from, address to, uint256[] calldata ids, uint256[] calldata amountsToBurn ) external returns (bytes4); function afterBurn( address sender, address from, address to, uint256[] calldata ids, uint256[] calldata amountsToBurn ) external returns (bytes4); function beforeBatchTransferFrom( address sender, address from, address to, uint256[] calldata ids, uint256[] calldata amounts ) external returns (bytes4); function afterBatchTransferFrom( address sender, address from, address to, uint256[] calldata ids, uint256[] calldata amounts ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol) pragma solidity ^0.8.20; /** * @dev External interface of AccessControl declared to support ERC-165 detection. */ interface IAccessControl { /** * @dev The `account` is missing a role. */ error AccessControlUnauthorizedAccount(address account, bytes32 neededRole); /** * @dev The caller of a function is not the expected one. * * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}. */ error AccessControlBadConfirmation(); /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `callerConfirmation`. */ function renounceRole(bytes32 role, address callerConfirmation) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /** * @title Liquidity Book Constants Library * @author Trader Joe * @notice Set of constants for Liquidity Book contracts */ library Constants { uint8 internal constant SCALE_OFFSET = 128; uint256 internal constant SCALE = 1 << SCALE_OFFSET; uint256 internal constant PRECISION = 1e18; uint256 internal constant SQUARED_PRECISION = PRECISION * PRECISION; uint256 internal constant MAX_FEE = 0.1e18; // 10% uint256 internal constant MAX_PROTOCOL_SHARE = 2_500; // 25% of the fee uint256 internal constant BASIS_POINT_MAX = 10_000; // (2^256 - 1) / (2 * log(2**128) / log(1.0001)) uint256 internal constant MAX_LIQUIDITY_PER_BIN = 65251743116719673010965625540244653191619923014385985379600384103134737; /// @dev The expected return after a successful flash loan bytes32 internal constant CALLBACK_SUCCESS = keccak256("LBPair.onFlashLoan"); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {Constants} from "../Constants.sol"; import {BitMath} from "./BitMath.sol"; /** * @title Liquidity Book Uint128x128 Math Library * @author Trader Joe * @notice Helper contract used for power and log calculations */ library Uint128x128Math { using BitMath for uint256; error Uint128x128Math__LogUnderflow(); error Uint128x128Math__PowUnderflow(uint256 x, int256 y); uint256 constant LOG_SCALE_OFFSET = 127; uint256 constant LOG_SCALE = 1 << LOG_SCALE_OFFSET; uint256 constant LOG_SCALE_SQUARED = LOG_SCALE * LOG_SCALE; /** * @notice Calculates the binary logarithm of x. * @dev Based on the iterative approximation algorithm. * https://en.wikipedia.org/wiki/Binary_logarithm#Iterative_approximation * Requirements: * - x must be greater than zero. * Caveats: * - The results are not perfectly accurate to the last decimal, due to the lossy precision of the iterative approximation * Also because x is converted to an unsigned 129.127-binary fixed-point number during the operation to optimize the multiplication * @param x The unsigned 128.128-binary fixed-point number for which to calculate the binary logarithm. * @return result The binary logarithm as a signed 128.128-binary fixed-point number. */ function log2(uint256 x) internal pure returns (int256 result) { // Convert x to a unsigned 129.127-binary fixed-point number to optimize the multiplication. // If we use an offset of 128 bits, y would need 129 bits and y**2 would would overflow and we would have to // use mulDiv, by reducing x to 129.127-binary fixed-point number we assert that y will use 128 bits, and we // can use the regular multiplication if (x == 1) return -128; if (x == 0) revert Uint128x128Math__LogUnderflow(); x >>= 1; unchecked { // This works because log2(x) = -log2(1/x). int256 sign; if (x >= LOG_SCALE) { sign = 1; } else { sign = -1; // Do the fixed-point inversion inline to save gas x = LOG_SCALE_SQUARED / x; } // Calculate the integer part of the logarithm and add it to the result and finally calculate y = x * 2^(-n). uint256 n = (x >> LOG_SCALE_OFFSET).mostSignificantBit(); // The integer part of the logarithm as a signed 129.127-binary fixed-point number. The operation can't overflow // because n is maximum 255, LOG_SCALE_OFFSET is 127 bits and sign is either 1 or -1. result = int256(n) << LOG_SCALE_OFFSET; // This is y = x * 2^(-n). uint256 y = x >> n; // If y = 1, the fractional part is zero. if (y != LOG_SCALE) { // Calculate the fractional part via the iterative approximation. // The "delta >>= 1" part is equivalent to "delta /= 2", but shifting bits is faster. for (int256 delta = int256(1 << (LOG_SCALE_OFFSET - 1)); delta > 0; delta >>= 1) { y = (y * y) >> LOG_SCALE_OFFSET; // Is y^2 > 2 and so in the range [2,4)? if (y >= 1 << (LOG_SCALE_OFFSET + 1)) { // Add the 2^(-m) factor to the logarithm. result += delta; // Corresponds to z/2 on Wikipedia. y >>= 1; } } } // Convert x back to unsigned 128.128-binary fixed-point number result = (result * sign) << 1; } } /** * @notice Returns the value of x^y. It calculates `1 / x^abs(y)` if x is bigger than 2^128. * At the end of the operations, we invert the result if needed. * @param x The unsigned 128.128-binary fixed-point number for which to calculate the power * @param y A relative number without any decimals, needs to be between ]-2^21; 2^21[ */ function pow(uint256 x, int256 y) internal pure returns (uint256 result) { bool invert; uint256 absY; if (y == 0) return Constants.SCALE; assembly { absY := y if slt(absY, 0) { absY := sub(0, absY) invert := iszero(invert) } } if (absY < 0x100000) { result = Constants.SCALE; assembly { let squared := x if gt(x, 0xffffffffffffffffffffffffffffffff) { squared := div(not(0), squared) invert := iszero(invert) } if and(absY, 0x1) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x2) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x4) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x8) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x10) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x20) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x40) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x80) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x100) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x200) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x400) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x800) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x1000) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x2000) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x4000) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x8000) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x10000) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x20000) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x40000) { result := shr(128, mul(result, squared)) } squared := shr(128, mul(squared, squared)) if and(absY, 0x80000) { result := shr(128, mul(result, squared)) } } } // revert if y is too big or if x^y underflowed if (result == 0) revert Uint128x128Math__PowUnderflow(x, y); return invert ? type(uint256).max / result : result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {BitMath} from "./BitMath.sol"; /** * @title Liquidity Book Uint256x256 Math Library * @author Trader Joe * @notice Helper contract used for full precision calculations */ library Uint256x256Math { error Uint256x256Math__MulShiftOverflow(); error Uint256x256Math__MulDivOverflow(); /** * @notice Calculates floor(x*y/denominator) with full precision * The result will be rounded down * @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv * Requirements: * - The denominator cannot be zero * - The result must fit within uint256 * Caveats: * - This function does not work with fixed-point numbers * @param x The multiplicand as an uint256 * @param y The multiplier as an uint256 * @param denominator The divisor as an uint256 * @return result The result as an uint256 */ function mulDivRoundDown(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { (uint256 prod0, uint256 prod1) = _getMulProds(x, y); return _getEndOfDivRoundDown(x, y, denominator, prod0, prod1); } /** * @notice Calculates ceil(x*y/denominator) with full precision * The result will be rounded up * @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv * Requirements: * - The denominator cannot be zero * - The result must fit within uint256 * Caveats: * - This function does not work with fixed-point numbers * @param x The multiplicand as an uint256 * @param y The multiplier as an uint256 * @param denominator The divisor as an uint256 * @return result The result as an uint256 */ function mulDivRoundUp(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { result = mulDivRoundDown(x, y, denominator); if (mulmod(x, y, denominator) != 0) result += 1; } /** * @notice Calculates floor(x * y / 2**offset) with full precision * The result will be rounded down * @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv * Requirements: * - The offset needs to be strictly lower than 256 * - The result must fit within uint256 * Caveats: * - This function does not work with fixed-point numbers * @param x The multiplicand as an uint256 * @param y The multiplier as an uint256 * @param offset The offset as an uint256, can't be greater than 256 * @return result The result as an uint256 */ function mulShiftRoundDown(uint256 x, uint256 y, uint8 offset) internal pure returns (uint256 result) { (uint256 prod0, uint256 prod1) = _getMulProds(x, y); if (prod0 != 0) result = prod0 >> offset; if (prod1 != 0) { // Make sure the result is less than 2^256. if (prod1 >= 1 << offset) revert Uint256x256Math__MulShiftOverflow(); unchecked { result += prod1 << (256 - offset); } } } /** * @notice Calculates floor(x * y / 2**offset) with full precision * The result will be rounded down * @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv * Requirements: * - The offset needs to be strictly lower than 256 * - The result must fit within uint256 * Caveats: * - This function does not work with fixed-point numbers * @param x The multiplicand as an uint256 * @param y The multiplier as an uint256 * @param offset The offset as an uint256, can't be greater than 256 * @return result The result as an uint256 */ function mulShiftRoundUp(uint256 x, uint256 y, uint8 offset) internal pure returns (uint256 result) { result = mulShiftRoundDown(x, y, offset); if (mulmod(x, y, 1 << offset) != 0) result += 1; } /** * @notice Calculates floor(x << offset / y) with full precision * The result will be rounded down * @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv * Requirements: * - The offset needs to be strictly lower than 256 * - The result must fit within uint256 * Caveats: * - This function does not work with fixed-point numbers * @param x The multiplicand as an uint256 * @param offset The number of bit to shift x as an uint256 * @param denominator The divisor as an uint256 * @return result The result as an uint256 */ function shiftDivRoundDown(uint256 x, uint8 offset, uint256 denominator) internal pure returns (uint256 result) { uint256 prod0; uint256 prod1; prod0 = x << offset; // Least significant 256 bits of the product unchecked { prod1 = x >> (256 - offset); // Most significant 256 bits of the product } return _getEndOfDivRoundDown(x, 1 << offset, denominator, prod0, prod1); } /** * @notice Calculates ceil(x << offset / y) with full precision * The result will be rounded up * @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv * Requirements: * - The offset needs to be strictly lower than 256 * - The result must fit within uint256 * Caveats: * - This function does not work with fixed-point numbers * @param x The multiplicand as an uint256 * @param offset The number of bit to shift x as an uint256 * @param denominator The divisor as an uint256 * @return result The result as an uint256 */ function shiftDivRoundUp(uint256 x, uint8 offset, uint256 denominator) internal pure returns (uint256 result) { result = shiftDivRoundDown(x, offset, denominator); if (mulmod(x, 1 << offset, denominator) != 0) result += 1; } /** * @notice Helper function to return the result of `x * y` as 2 uint256 * @param x The multiplicand as an uint256 * @param y The multiplier as an uint256 * @return prod0 The least significant 256 bits of the product * @return prod1 The most significant 256 bits of the product */ function _getMulProds(uint256 x, uint256 y) private pure returns (uint256 prod0, uint256 prod1) { // 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. assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } } /** * @notice Helper function to return the result of `x * y / denominator` with full precision * @param x The multiplicand as an uint256 * @param y The multiplier as an uint256 * @param denominator The divisor as an uint256 * @param prod0 The least significant 256 bits of the product * @param prod1 The most significant 256 bits of the product * @return result The result as an uint256 */ function _getEndOfDivRoundDown(uint256 x, uint256 y, uint256 denominator, uint256 prod0, uint256 prod1) private pure returns (uint256 result) { // Handle non-overflow cases, 256 by 256 division if (prod1 == 0) { unchecked { result = prod0 / denominator; } } else { // Make sure the result is less than 2^256. Also prevents denominator == 0 if (prod1 >= denominator) revert Uint256x256Math__MulDivOverflow(); // 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 unchecked { // Does not overflow because the denominator cannot be zero at this stage in the function uint256 lpotdod = denominator & (~denominator + 1); assembly { // Divide denominator by lpotdod. denominator := div(denominator, lpotdod) // Divide [prod1 prod0] by lpotdod. prod0 := div(prod0, lpotdod) // Flip lpotdod such that it is 2^256 / lpotdod. If lpotdod is zero, then it becomes one lpotdod := add(div(sub(0, lpotdod), lpotdod), 1) } // Shift in bits from prod1 into prod0 prod0 |= prod1 * lpotdod; // 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; } } } /** * @notice Calculates the square root of x * @dev Credit to OpenZeppelin's Math library under MIT license */ function sqrt(uint256 x) internal pure returns (uint256 sqrtX) { if (x == 0) return 0; uint256 msb = BitMath.mostSignificantBit(x); assembly { sqrtX := shl(shr(1, msb), 1) sqrtX := shr(1, add(sqrtX, div(x, sqrtX))) sqrtX := shr(1, add(sqrtX, div(x, sqrtX))) sqrtX := shr(1, add(sqrtX, div(x, sqrtX))) sqrtX := shr(1, add(sqrtX, div(x, sqrtX))) sqrtX := shr(1, add(sqrtX, div(x, sqrtX))) sqrtX := shr(1, add(sqrtX, div(x, sqrtX))) sqrtX := shr(1, add(sqrtX, div(x, sqrtX))) x := div(x, sqrtX) } return sqrtX < x ? sqrtX : x; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; /// @title Liquidity Book Flashloan Callback Interface /// @author Trader Joe /// @notice Required interface to interact with LB flash loans interface ILBFlashLoanCallback { function LBFlashLoanCallback( address sender, IERC20 tokenX, IERC20 tokenY, bytes32 amounts, bytes32 totalFees, bytes calldata data ) external returns (bytes32); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /** * @title Liquidity Book Token Interface * @author Trader Joe * @notice Interface to interact with the LBToken. */ interface ILBToken { error LBToken__AddressThisOrZero(); error LBToken__InvalidLength(); error LBToken__SelfApproval(address owner); error LBToken__SpenderNotApproved(address from, address spender); error LBToken__TransferExceedsBalance(address from, uint256 id, uint256 amount); error LBToken__BurnExceedsBalance(address from, uint256 id, uint256 amount); event TransferBatch( address indexed sender, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); event ApprovalForAll(address indexed account, address indexed sender, bool approved); function name() external view returns (string memory); function symbol() external view returns (string memory); function totalSupply(uint256 id) external view returns (uint256); function balanceOf(address account, uint256 id) external view returns (uint256); function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); function isApprovedForAll(address owner, address spender) external view returns (bool); function approveForAll(address spender, bool approved) external; function batchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[ERC]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.10; /** * @title Liquidity Book Bit Math Library * @author Trader Joe * @notice Helper contract used for bit calculations */ library BitMath { /** * @dev Returns the index of the closest bit on the right of x that is non null * @param x The value as a uint256 * @param bit The index of the bit to start searching at * @return id The index of the closest non null bit on the right of x. * If there is no closest bit, it returns max(uint256) */ function closestBitRight(uint256 x, uint8 bit) internal pure returns (uint256 id) { unchecked { uint256 shift = 255 - bit; x <<= shift; // can't overflow as it's non-zero and we shifted it by `_shift` return (x == 0) ? type(uint256).max : mostSignificantBit(x) - shift; } } /** * @dev Returns the index of the closest bit on the left of x that is non null * @param x The value as a uint256 * @param bit The index of the bit to start searching at * @return id The index of the closest non null bit on the left of x. * If there is no closest bit, it returns max(uint256) */ function closestBitLeft(uint256 x, uint8 bit) internal pure returns (uint256 id) { unchecked { x >>= bit; return (x == 0) ? type(uint256).max : leastSignificantBit(x) + bit; } } /** * @dev Returns the index of the most significant bit of x * This function returns 0 if x is 0 * @param x The value as a uint256 * @return msb The index of the most significant bit of x */ function mostSignificantBit(uint256 x) internal pure returns (uint8 msb) { assembly { if gt(x, 0xffffffffffffffffffffffffffffffff) { x := shr(128, x) msb := 128 } if gt(x, 0xffffffffffffffff) { x := shr(64, x) msb := add(msb, 64) } if gt(x, 0xffffffff) { x := shr(32, x) msb := add(msb, 32) } if gt(x, 0xffff) { x := shr(16, x) msb := add(msb, 16) } if gt(x, 0xff) { x := shr(8, x) msb := add(msb, 8) } if gt(x, 0xf) { x := shr(4, x) msb := add(msb, 4) } if gt(x, 0x3) { x := shr(2, x) msb := add(msb, 2) } if gt(x, 0x1) { msb := add(msb, 1) } } } /** * @dev Returns the index of the least significant bit of x * This function returns 255 if x is 0 * @param x The value as a uint256 * @return lsb The index of the least significant bit of x */ function leastSignificantBit(uint256 x) internal pure returns (uint8 lsb) { assembly { let sx := shl(128, x) if iszero(iszero(sx)) { lsb := 128 x := sx } sx := shl(64, x) if iszero(iszero(sx)) { x := sx lsb := add(lsb, 64) } sx := shl(32, x) if iszero(iszero(sx)) { x := sx lsb := add(lsb, 32) } sx := shl(16, x) if iszero(iszero(sx)) { x := sx lsb := add(lsb, 16) } sx := shl(8, x) if iszero(iszero(sx)) { x := sx lsb := add(lsb, 8) } sx := shl(4, x) if iszero(iszero(sx)) { x := sx lsb := add(lsb, 4) } sx := shl(2, x) if iszero(iszero(sx)) { x := sx lsb := add(lsb, 2) } if iszero(iszero(shl(1, x))) { lsb := add(lsb, 1) } lsb := sub(255, lsb) } } }
{ "remappings": [ "ds-test/=lib/forge-std/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 360 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"feeRecipient","type":"address"},{"internalType":"address","name":"initialOwner","type":"address"},{"internalType":"uint256","name":"flashLoanFee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"EnumerableMapNonexistentKey","type":"error"},{"inputs":[],"name":"LBFactory__AddressZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"binStep","type":"uint256"}],"name":"LBFactory__BinStepHasNoPreset","type":"error"},{"inputs":[{"internalType":"uint256","name":"binStep","type":"uint256"}],"name":"LBFactory__BinStepTooLow","type":"error"},{"inputs":[],"name":"LBFactory__CannotGrantDefaultAdminRole","type":"error"},{"inputs":[{"internalType":"uint256","name":"fees","type":"uint256"},{"internalType":"uint256","name":"maxFees","type":"uint256"}],"name":"LBFactory__FlashLoanFeeAboveMax","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"LBFactory__IdenticalAddresses","type":"error"},{"inputs":[],"name":"LBFactory__ImplementationNotSet","type":"error"},{"inputs":[],"name":"LBFactory__InvalidHooksParameters","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"tokenX","type":"address"},{"internalType":"contract IERC20","name":"tokenY","type":"address"},{"internalType":"uint256","name":"_binStep","type":"uint256"}],"name":"LBFactory__LBPairAlreadyExists","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"tokenX","type":"address"},{"internalType":"contract IERC20","name":"tokenY","type":"address"},{"internalType":"uint256","name":"binStep","type":"uint256"}],"name":"LBFactory__LBPairDoesNotExist","type":"error"},{"inputs":[],"name":"LBFactory__LBPairIgnoredIsAlreadyInTheSameState","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"tokenX","type":"address"},{"internalType":"contract IERC20","name":"tokenY","type":"address"},{"internalType":"uint256","name":"binStep","type":"uint256"}],"name":"LBFactory__LBPairNotCreated","type":"error"},{"inputs":[{"internalType":"address","name":"LBPairImplementation","type":"address"}],"name":"LBFactory__LBPairSafetyCheckFailed","type":"error"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"binStep","type":"uint256"}],"name":"LBFactory__PresetIsLockedForUsers","type":"error"},{"inputs":[],"name":"LBFactory__PresetOpenStateIsAlreadyInTheSameState","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"quoteAsset","type":"address"}],"name":"LBFactory__QuoteAssetAlreadyWhitelisted","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"quoteAsset","type":"address"}],"name":"LBFactory__QuoteAssetNotWhitelisted","type":"error"},{"inputs":[{"internalType":"address","name":"feeRecipient","type":"address"}],"name":"LBFactory__SameFeeRecipient","type":"error"},{"inputs":[{"internalType":"uint256","name":"flashLoanFee","type":"uint256"}],"name":"LBFactory__SameFlashLoanFee","type":"error"},{"inputs":[{"internalType":"address","name":"hooksImplementation","type":"address"}],"name":"LBFactory__SameHooksImplementation","type":"error"},{"inputs":[{"internalType":"bytes32","name":"hooksParameters","type":"bytes32"}],"name":"LBFactory__SameHooksParameters","type":"error"},{"inputs":[{"internalType":"address","name":"LBPairImplementation","type":"address"}],"name":"LBFactory__SameImplementation","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"PairParametersHelper__InvalidParameter","type":"error"},{"inputs":[],"name":"SafeCast__Exceeds16Bits","type":"error"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"int256","name":"y","type":"int256"}],"name":"Uint128x128Math__PowUnderflow","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldRecipient","type":"address"},{"indexed":false,"internalType":"address","name":"newRecipient","type":"address"}],"name":"FeeRecipientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldFlashLoanFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newFlashLoanFee","type":"uint256"}],"name":"FlashLoanFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"tokenX","type":"address"},{"indexed":true,"internalType":"contract IERC20","name":"tokenY","type":"address"},{"indexed":true,"internalType":"uint256","name":"binStep","type":"uint256"},{"indexed":false,"internalType":"contract ILBPair","name":"LBPair","type":"address"},{"indexed":false,"internalType":"uint256","name":"pid","type":"uint256"}],"name":"LBPairCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract ILBPair","name":"LBPair","type":"address"},{"indexed":false,"internalType":"bool","name":"ignored","type":"bool"}],"name":"LBPairIgnoredStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldLBPairImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"LBPairImplementation","type":"address"}],"name":"LBPairImplementationSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"binStep","type":"uint256"},{"indexed":true,"internalType":"bool","name":"isOpen","type":"bool"}],"name":"PresetOpenStateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"binStep","type":"uint256"}],"name":"PresetRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"binStep","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"baseFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"filterPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"decayPeriod","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reductionFactor","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"variableFeeControl","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"protocolShare","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxVolatilityAccumulator","type":"uint256"}],"name":"PresetSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"quoteAsset","type":"address"}],"name":"QuoteAssetAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"contract IERC20","name":"quoteAsset","type":"address"}],"name":"QuoteAssetRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"LB_HOOKS_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"quoteAsset","type":"address"}],"name":"addQuoteAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenX","type":"address"},{"internalType":"contract IERC20","name":"tokenY","type":"address"},{"internalType":"uint24","name":"activeId","type":"uint24"},{"internalType":"uint16","name":"binStep","type":"uint16"}],"name":"createLBPair","outputs":[{"internalType":"contract ILBPair","name":"pair","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ILBPair","name":"pair","type":"address"}],"name":"forceDecay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllBinSteps","outputs":[{"internalType":"uint256[]","name":"binStepWithPreset","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenX","type":"address"},{"internalType":"contract IERC20","name":"tokenY","type":"address"}],"name":"getAllLBPairs","outputs":[{"components":[{"internalType":"uint16","name":"binStep","type":"uint16"},{"internalType":"contract ILBPair","name":"LBPair","type":"address"},{"internalType":"bool","name":"createdByOwner","type":"bool"},{"internalType":"bool","name":"ignoredForRouting","type":"bool"}],"internalType":"struct ILBFactory.LBPairInformation[]","name":"lbPairsAvailable","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFeeRecipient","outputs":[{"internalType":"address","name":"feeRecipient","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFlashLoanFee","outputs":[{"internalType":"uint256","name":"flashLoanFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getLBPairAtIndex","outputs":[{"internalType":"contract ILBPair","name":"lbPair","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLBPairImplementation","outputs":[{"internalType":"address","name":"lbPairImplementation","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenA","type":"address"},{"internalType":"contract IERC20","name":"tokenB","type":"address"},{"internalType":"uint256","name":"binStep","type":"uint256"}],"name":"getLBPairInformation","outputs":[{"components":[{"internalType":"uint16","name":"binStep","type":"uint16"},{"internalType":"contract ILBPair","name":"LBPair","type":"address"},{"internalType":"bool","name":"createdByOwner","type":"bool"},{"internalType":"bool","name":"ignoredForRouting","type":"bool"}],"internalType":"struct ILBFactory.LBPairInformation","name":"lbPairInformation","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxFlashLoanFee","outputs":[{"internalType":"uint256","name":"maxFee","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getMinBinStep","outputs":[{"internalType":"uint256","name":"minBinStep","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"getNumberOfLBPairs","outputs":[{"internalType":"uint256","name":"lbPairNumber","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumberOfQuoteAssets","outputs":[{"internalType":"uint256","name":"numberOfQuoteAssets","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getOpenBinSteps","outputs":[{"internalType":"uint256[]","name":"openBinStep","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"binStep","type":"uint256"}],"name":"getPreset","outputs":[{"internalType":"uint256","name":"baseFactor","type":"uint256"},{"internalType":"uint256","name":"filterPeriod","type":"uint256"},{"internalType":"uint256","name":"decayPeriod","type":"uint256"},{"internalType":"uint256","name":"reductionFactor","type":"uint256"},{"internalType":"uint256","name":"variableFeeControl","type":"uint256"},{"internalType":"uint256","name":"protocolShare","type":"uint256"},{"internalType":"uint256","name":"maxVolatilityAccumulator","type":"uint256"},{"internalType":"bool","name":"isOpen","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getQuoteAssetAtIndex","outputs":[{"internalType":"contract IERC20","name":"asset","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"isQuoteAsset","outputs":[{"internalType":"bool","name":"isQuote","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenX","type":"address"},{"internalType":"contract IERC20","name":"tokenY","type":"address"},{"internalType":"uint16","name":"binStep","type":"uint16"}],"name":"removeLBHooksOnPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"binStep","type":"uint16"}],"name":"removePreset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"quoteAsset","type":"address"}],"name":"removeQuoteAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeRecipient","type":"address"}],"name":"setFeeRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenX","type":"address"},{"internalType":"contract IERC20","name":"tokenY","type":"address"},{"internalType":"uint16","name":"binStep","type":"uint16"},{"internalType":"uint16","name":"baseFactor","type":"uint16"},{"internalType":"uint16","name":"filterPeriod","type":"uint16"},{"internalType":"uint16","name":"decayPeriod","type":"uint16"},{"internalType":"uint16","name":"reductionFactor","type":"uint16"},{"internalType":"uint24","name":"variableFeeControl","type":"uint24"},{"internalType":"uint16","name":"protocolShare","type":"uint16"},{"internalType":"uint24","name":"maxVolatilityAccumulator","type":"uint24"}],"name":"setFeesParametersOnPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"flashLoanFee","type":"uint256"}],"name":"setFlashLoanFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenX","type":"address"},{"internalType":"contract IERC20","name":"tokenY","type":"address"},{"internalType":"uint16","name":"binStep","type":"uint16"},{"internalType":"bytes32","name":"hooksParameters","type":"bytes32"},{"internalType":"bytes","name":"onHooksSetData","type":"bytes"}],"name":"setLBHooksParametersOnPair","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"tokenX","type":"address"},{"internalType":"contract IERC20","name":"tokenY","type":"address"},{"internalType":"uint16","name":"binStep","type":"uint16"},{"internalType":"bool","name":"ignored","type":"bool"}],"name":"setLBPairIgnored","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newLBPairImplementation","type":"address"}],"name":"setLBPairImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"binStep","type":"uint16"},{"internalType":"uint16","name":"baseFactor","type":"uint16"},{"internalType":"uint16","name":"filterPeriod","type":"uint16"},{"internalType":"uint16","name":"decayPeriod","type":"uint16"},{"internalType":"uint16","name":"reductionFactor","type":"uint16"},{"internalType":"uint24","name":"variableFeeControl","type":"uint24"},{"internalType":"uint16","name":"protocolShare","type":"uint16"},{"internalType":"uint24","name":"maxVolatilityAccumulator","type":"uint24"},{"internalType":"bool","name":"isOpen","type":"bool"}],"name":"setPreset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"binStep","type":"uint16"},{"internalType":"bool","name":"isOpen","type":"bool"}],"name":"setPresetOpenState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b506040516200310938038062003109833981016040819052620000349162000253565b816001600160a01b0381166200006557604051631e4fbdf760e01b8152600060048201526024015b60405180910390fd5b620000708162000100565b5067016345785d8a0000811115620000ad57604051635e8988c160e01b81526004810182905267016345785d8a000060248201526044016200005c565b620000b8836200011e565b60048190556040805160008152602081018390527f5c34e91c94c78b662a45d0bd4a25a4e32c584c54a45a76e4a4d43be27ba40e50910160405180910390a150505062000294565b600180546001600160a01b03191690556200011b81620001e6565b50565b6001600160a01b0381166200014657604051632573cfb960e21b815260040160405180910390fd5b6003546001600160a01b0390811690821681036200018757600354604051634fcea97160e01b81526001600160a01b0390911660048201526024016200005c565b600380546001600160a01b0319166001600160a01b0384811691821790925560408051928416835260208301919091527f15d80a013f22151bc7246e3bc132e12828cde19de98870475e3fa70840152721910160405180910390a15050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200024e57600080fd5b919050565b6000806000606084860312156200026957600080fd5b620002748462000236565b9250620002846020850162000236565b9150604084015190509250925092565b612e6580620002a46000396000f3fe608060405234801561001057600080fd5b506004361061027e5760003560e01c8063701ab8c111610156578063aabc4b3c116100d3578063e203a31f11610097578063e92d0d5d11610071578063e92d0d5d146105c7578063f2fde38b146105da578063fd90c2be146105ed57600080fd5b8063e203a31f14610590578063e30c3978146105a3578063e74b981b146105b457600080fd5b8063aabc4b3c146104f6578063af37106514610546578063b038478114610557578063d547741f1461056a578063ddbfd9411461057d57600080fd5b806380c5061e1161011a57806380c5061e146104b45780638ce9aa1c146104bc5780638da5cb5b146104ca57806391d14854146104db578063a217fddf146104ee57600080fd5b8063701ab8c11461046a578063704037bd14610471578063715018a61461049157806379ba5097146104995780637daf5d66146104a157600080fd5b8063379ee803116101ff5780634e937c3a116101c3578063659ac74b1161019d578063659ac74b146104245780636622e0d71461043757806369d56ea31461045757600080fd5b80634e937c3a146104015780635a440923146104095780635b35875c1461041c57600080fd5b8063379ee803146103a45780633a2f1a91146103b75780633c78a941146103ca5780634ccb20c0146103dd5780634cd161d3146103ee57600080fd5b8063248a9ca311610246578063248a9ca31461033557806327721842146103585780632cc06b8c1461036b5780632f2ff15d1461037e57806336568abe1461039157600080fd5b806301ffc9a7146102835780630282c9c1146102ab5780630752092b146102c0578063093ff769146102eb5780631af5bacc14610300575b600080fd5b61029661029136600461276f565b6105f5565b60405190151581526020015b60405180910390f35b6102b361062c565b6040516102a29190612799565b6102d36102ce3660046127dd565b610706565b6040516001600160a01b0390911681526020016102a2565b6102fe6102f9366004612830565b610713565b005b6103277fdcf4465aa60d92459eb361fac2489220ae3c524301cc0433c30a5d83e8fb0fa981565b6040519081526020016102a2565b6103276103433660046127dd565b60009081526002602052604090206001015490565b6102966103663660046128ee565b610819565b6102fe61037936600461290b565b610826565b6102fe61038c366004612952565b610875565b6102fe61039f366004612952565b61089a565b6102fe6103b2366004612992565b6108d2565b6102fe6103c5366004612a3a565b6109ee565b6102fe6103d83660046128ee565b610aa0565b6003546001600160a01b03166102d3565b6102fe6103fc366004612aeb565b610afe565b600654610327565b6102fe6104173660046128ee565b610bc9565b6102b3610c3b565b6102d3610432366004612b1e565b610c4c565b61044a610445366004612b76565b611174565b6040516102a29190612ba4565b6102fe610465366004612c18565b61130c565b6001610327565b61048461047f366004612c65565b611496565b6040516102a29190612ca6565b6102fe6114cd565b6102fe6114e1565b6102d36104af3660046127dd565b611525565b610327611555565b67016345785d8a0000610327565b6000546001600160a01b03166102d3565b6102966104e9366004612952565b611561565b610327600081565b6105096105043660046127dd565b6115ad565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c0830152151560e0820152610100016102a2565b6005546001600160a01b03166102d3565b6102fe6105653660046128ee565b61166e565b6102fe610578366004612952565b6117af565b6102fe61058b3660046128ee565b6117d4565b6102fe61059e366004612ce2565b611846565b6001546001600160a01b03166102d3565b6102fe6105c23660046128ee565b6118b2565b6102fe6105d53660046127dd565b6118c3565b6102fe6105e83660046128ee565b611966565b600454610327565b60006001600160e01b03198216637965db0b60e01b148061062657506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600061063a60086119d7565b90508015610702578067ffffffffffffffff81111561065b5761065b612cfd565b604051908082528060200260200182016040528015610684578160200160208202803683370190505b5091506000805b828110156106f3576000806106a16008846119e2565b90925090506106af816119fe565b156106e057818685815181106106c7576106c7612d13565b6020908102919091010152836106dc81612d3f565b9450505b5050806106ec90612d3f565b905061068b565b5081811015610700578083525b505b5090565b6000610626600b83611a0a565b61071b611a16565b600061072c8b8b8b61ffff16611a43565b6020015190506001600160a01b03811661077b5760405163b65ee95360e01b81526001600160a01b03808d1660048301528b16602482015261ffff8a1660448201526064015b60405180910390fd5b604051633329c28d60e11b815261ffff808a16600483015280891660248301528088166044830152808716606483015262ffffff808716608484015290851660a4830152831660c48201526001600160a01b03821690636653851a9060e401600060405180830381600087803b1580156107f457600080fd5b505af1158015610808573d6000803e3d6000fd5b505050505050505050505050505050565b6000610626600b83611aed565b7fdcf4465aa60d92459eb361fac2489220ae3c524301cc0433c30a5d83e8fb0fa961085081611b0f565b6040805160008082526020820190925261086f91869186918691611b19565b50505050565b60008281526002602052604090206001015461089081611b0f565b61086f8383611c60565b6001600160a01b03811633146108c35760405163334bd91960e11b815260040160405180910390fd5b6108cd8282611c8a565b505050565b6108da611a16565b60018961ffff16101561090657604051634f958e7160e01b815261ffff8a166004820152602401610772565b6000610918818a8a8a8a8a8a8a611cff565b905081156109305761092d81600160ff611dff565b90505b610940600861ffff8c1683611e26565b506040805161ffff8b811682528a8116602083015289811682840152888116606083015262ffffff888116608084015287821660a0840152861660c08301529151918c16917f839844a256a87f87c9c835117d9a1c40be013954064c937072acb32d36db6a289181900360e00190a26040518215159061ffff8c16907f58a8b6a02b964cca2712e5a71d7b0d564a56b4a0f573b4c47f389341ade14cfd90600090a350505050505050505050565b7fdcf4465aa60d92459eb361fac2489220ae3c524301cc0433c30a5d83e8fb0fa9610a1881611b0f565b6001600160a01b0384161580610a365750836001600160a01b031916155b15610a545760405163d43a15d160e01b815260040160405180910390fd5b610a978787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b1992505050565b50505050505050565b610aa8611a16565b806001600160a01b031663d3b9fbe46040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ae357600080fd5b505af1158015610af7573d6000803e3d6000fd5b5050505050565b610b06611a16565b610b15600861ffff8416611e33565b610b3857604051637d9160bf60e11b815261ffff83166004820152602401610772565b6000610b49600861ffff8516611e3f565b905081151560ff82901c151503610b73576040516311be38db60e11b815260040160405180910390fd5b610b9061ffff8416610b87838560ff611dff565b60089190611e26565b506040518215159061ffff8516907f58a8b6a02b964cca2712e5a71d7b0d564a56b4a0f573b4c47f389341ade14cfd90600090a3505050565b610bd1611a16565b610bdc600b82611e4b565b610c04576040516303ce0ad960e01b81526001600160a01b0382166004820152602401610772565b6040516001600160a01b038216907f84cc2115995684dcb0cd3d3a9565e3d32f075de81db70c8dc3a719b2a47af67e90600090a250565b6060610c476008611e60565b905090565b6000610c5d600861ffff8416611e33565b610c8057604051637d9160bf60e11b815261ffff83166004820152602401610772565b6000610c91600861ffff8516611e3f565b90506000610ca76000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316149050610cc6826119fe565b158015610cd1575080155b15610cfb576040516304fc2fe760e11b815233600482015261ffff85166024820152604401610772565b610d06600b87611aed565b610d2e57604051638e888ef360e01b81526001600160a01b0387166004820152602401610772565b856001600160a01b0316876001600160a01b031603610d6b57604051632f9b185360e01b81526001600160a01b0388166004820152602401610772565b610d758585611e6d565b50600080610d838989611ea4565b90925090506001600160a01b038216610daf57604051632573cfb960e21b815260040160405180910390fd5b6001600160a01b0382811660009081526007602090815260408083208585168452825280832061ffff8b1684529091529020546201000090041615610e245760405163cb27a43560e01b81526001600160a01b03808b1660048301528916602482015261ffff87166044820152606401610772565b6005546001600160a01b031680610e4e576040516328b4fcf960e21b815260040160405180910390fd5b6040516bffffffffffffffffffffffff1960608c811b821660208401528b901b1660348201527fffff00000000000000000000000000000000000000000000000000000000000060f089901b166048820152610efb908290604a0160408051601f198184030181528282526001600160a01b03808916602085015287169183019190915261ffff8b1660608301529060800160405160208183030381529060405280519060200120611ecd565b6040805160808101825261ffff808b168083526001600160a01b0380861660208086018281528c15158789019081526000606089018181528e8716808352600786528b83208f89168085529087528c84208a855287528c84209b518c549651955193511515600160b81b0260ff60b81b19941515600160b01b029490941661ffff60b01b1996909a16620100000275ffffffffffffffffffffffffffffffffffffffffffff199097169b169a909a179490941792909216959095171790965560068054600181019091557ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0180546001600160a01b031916909217909155938152600d8452848120928152919092529190912091975061101b9250611f88565b508561ffff16886001600160a01b03168a6001600160a01b03167f2c8d104b27c6b7f4492017a6f5cf3803043688934ebcaa6a03540beeaf976aff8860016006805490506110699190612d58565b604080516001600160a01b03909316835260208301919091520160405180910390a4846001600160a01b03166347973bff6110a386611f94565b6110ac87611fa0565b6110b588611fb0565b6110be89611fc0565b6110c78a611fd0565b6110d08b611fe1565b6110d98c611ff1565b6040516001600160e01b031960e08a901b16815261ffff978816600482015295871660248701529386166044860152918516606485015262ffffff9081166084850152931660a4830152821660c4820152908a1660e482015261010401600060405180830381600087803b15801561115057600080fd5b505af1158015611164573d6000803e3d6000fd5b5050505050505050949350505050565b60606000806111838585611ea4565b6001600160a01b038083166000908152600d6020908152604080832093851683529290529081209294509092506111b982612002565b90508015611302578067ffffffffffffffff8111156111da576111da612cfd565b60405190808252806020026020018201604052801561122c57816020015b6040805160808101825260008082526020808301829052928201819052606082015282526000199092019101816111f85790505b506001600160a01b03808616600090815260076020908152604080832093881683529290529081209196505b828110156112ff57600061127461126f8684611a0a565b61200c565b6040805160808101825261ffff831680825260008181526020888152848220546001600160a01b03620100008204168286015260ff600160b01b8204811615159686019690965292909152879052600160b81b9004909116151560608201528951919250908990849081106112eb576112eb612d13565b602090810291909101015250600101611258565b50505b5050505092915050565b611314611a16565b6000806113218686611ea4565b6001600160a01b0380831660009081526007602090815260408083208486168452825280832061ffff808c1685529083529281902081516080810183529054938416815262010000840490941691840182905260ff600160b01b84048116151591850191909152600160b81b90920490911615156060830152929450909250906113db5760405163102a919160e21b81526001600160a01b0380891660048301528716602482015261ffff86166044820152606401610772565b831515816060015115150361140257604051626ee66560e11b815260040160405180910390fd5b6001600160a01b0380841660009081526007602090815260408083208685168452825280832061ffff8a1684528252918290208054881515600160b81b0260ff60b81b1990911617905583015190519116907f44cf35361c9ff3c8c1397ec6410d5495cc481feaef35c9af11da1a637107de4f9061148590871515815260200190565b60405180910390a250505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526114c5848484611a43565b949350505050565b6114d5611a16565b6114df6000612036565b565b60015433906001600160a01b031681146115195760405163118cdaa760e01b81526001600160a01b0382166004820152602401610772565b61152281612036565b50565b60006006828154811061153a5761153a612d13565b6000918252602090912001546001600160a01b031692915050565b6000610c47600b612002565b60008261157f57506000546001600160a01b03828116911614610626565b60008381526002602090815260408083206001600160a01b038616845290915290205460ff165b9392505050565b6000808080808080806115c160088a611e33565b6115e157604051637d9160bf60e11b8152600481018a9052602401610772565b60006115ee60088b611e3f565b90506115f981611f94565b61ffff16985061160881611fa0565b61ffff16975061161781611fb0565b61ffff16965061162681611fc0565b61ffff16955061163581611fd0565b62ffffff16945061164581611fe1565b61ffff16935061165481611ff1565b62ffffff16925060ff81901c915050919395975091939597565b611676611a16565b306001600160a01b0316816001600160a01b03166388cc58e46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e29190612d6b565b6001600160a01b03161461171457604051630a3e70af60e11b81526001600160a01b0382166004820152602401610772565b6005546001600160a01b03908116908216810361174f57604051630ded3b9560e31b81526001600160a01b0383166004820152602401610772565b600580546001600160a01b0319166001600160a01b0384811691821790925560408051928416835260208301919091527f900d0e3d359f50e4f923ecdc06b401e07dbb9f485e17b07bcfc91a13000b277e91015b60405180910390a15050565b6000828152600260205260409020600101546117ca81611b0f565b61086f8383611c8a565b6117dc611a16565b6117e7600b8261204f565b61180f57604051638e888ef360e01b81526001600160a01b0382166004820152602401610772565b6040516001600160a01b038216907f0b767739217755d8af5a2ba75b181a19fa1750f8bb701f09311cb19a90140cb390600090a250565b61184e611a16565b61185d600861ffff8316612064565b61188057604051637d9160bf60e11b815261ffff82166004820152602401610772565b60405161ffff8216907fdd86b848bb56ff540caa68683fa467d0e7eb5f8b2d44e4ee435742eeeae9be1390600090a250565b6118ba611a16565b61152281612070565b6118cb611a16565b6004548181036118f157604051631baa31e960e21b815260048101839052602401610772565b67016345785d8a000082111561192b57604051635e8988c160e01b81526004810183905267016345785d8a00006024820152604401610772565b600482905560408051828152602081018490527f5c34e91c94c78b662a45d0bd4a25a4e32c584c54a45a76e4a4d43be27ba40e5091016117a3565b61196e611a16565b600180546001600160a01b0383166001600160a01b0319909116811790915561199f6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60006106268261212e565b60008080806119f18686612139565b9097909650945050505050565b600060ff82901c610626565b60006115a68383612164565b6000546001600160a01b031633146114df5760405163118cdaa760e01b8152336004820152602401610772565b604080516080810182526000808252602082018190529181018290526060810191909152611a718484611ea4565b6001600160a01b03918216600090815260076020908152604080832093851683529281528282209582529485528190208151608081018352905461ffff811682526201000081049093169481019490945260ff600160b01b83048116151591850191909152600160b81b90910416151560608301525092915050565b6001600160a01b038116600090815260018301602052604081205415156115a6565b611522813361218e565b6000611b2a86868661ffff16611a43565b6020015190506001600160a01b038116611b745760405163b65ee95360e01b81526001600160a01b0380881660048301528616602482015261ffff85166044820152606401610772565b82816001600160a01b031663781a89156040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd79190612d88565b03611bf85760405163b70cd0db60e01b815260048101849052602401610772565b604051631b057f6d60e01b81526001600160a01b03821690631b057f6d90611c269086908690600401612da1565b600060405180830381600087803b158015611c4057600080fd5b505af1158015611c54573d6000803e3d6000fd5b50505050505050505050565b600082611c8057604051633e3253cf60e11b815260040160405180910390fd5b6115a683836121cb565b6000611c968383611561565b15611cf75760008381526002602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610626565b506000610626565b60008561ffff168761ffff161180611d1c5750610fff8661ffff16115b80611d2c57506127108561ffff16115b80611d3c57506109c48361ffff16115b80611d4e5750620fffff8262ffffff16115b15611d6c57604051631c07203f60e01b815260040160405180910390fd5b5060109590951b630fff00001661ffff9690961695909517601c9390931b64fff0000000169290921760289190911b663fff0000000000161760369190911b693fffffc00000000000001617604e9290921b6b0fffc00000000000000000001691909117605c9190911b6dfffff0000000000000000000000016176dffffffffffffffffffffffffffff19919091161790565b60006114c58484611e11576000611e14565b60015b600180861b19929092169116841b1790565b60006114c5848484612257565b60006115a68383612274565b60006115a68383612280565b60006115a6836001600160a01b0384166122c7565b606060006115a68361230e565b600061271061ffff60801b608084901b1604600160801b0162ffffff8416627fffff1901611e9b8282612319565b95945050505050565b600080826001600160a01b0316846001600160a01b03161115611ec5579192915b509192909150565b600060408303516020840351845180602087010180516002830161ffca811115611eff5763c8c781396000526004601cfd5b6c5af43d3d93803e603357fd5bf3895289600d8a03527d6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d738160481b176035820160d81b1760218a03528060f01b835287603f8201601f8b036000f596505085611f6e5763301164256000526004601cfd5b90528552601f19850152603f199093019290925250919050565b60006115a683836122c7565b600061ffff8216610626565b60006106268260101c610fff1690565b600061062682601c1c610fff1690565b60006106268260281c613fff1690565b60006106268260361c62ffffff1690565b600061062682604e1c613fff1690565b600061062682605c1c620fffff1690565b6000610626825490565b8061ffff81168114612031576040516364ae406d60e01b815260040160405180910390fd5b919050565b600180546001600160a01b031916905561152281612582565b60006115a6836001600160a01b0384166125d2565b60006115a683836126c5565b6001600160a01b03811661209757604051632573cfb960e21b815260040160405180910390fd5b6003546001600160a01b0390811690821681036120d657600354604051634fcea97160e01b81526001600160a01b039091166004820152602401610772565b600380546001600160a01b0319166001600160a01b0384811691821790925560408051928416835260208301919091527f15d80a013f22151bc7246e3bc132e12828cde19de98870475e3fa7084015272191016117a3565b600061062682612002565b600080806121478585611a0a565b600081815260029690960160205260409095205494959350505050565b600082600001828154811061217b5761217b612d13565b9060005260206000200154905092915050565b6121988282611561565b6121c75760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610772565b5050565b60006121d78383611561565b611cf75760008381526002602090815260408083206001600160a01b03861684529091529020805460ff1916600117905561220f3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610626565b600082815260028401602052604081208290556114c58484611f88565b60006115a683836126e2565b6000818152600283016020526040812054801580156122a657506122a48484612274565b155b156115a65760405163015ab34360e11b815260048101849052602401610772565b6000818152600183016020526040812054611cf757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610626565b6060610626826126fa565b6000806000836000036123355750600160801b91506106269050565b50826000811215612347579015906000035b6210000081101561254057600160801b9250846fffffffffffffffffffffffffffffffff81111561237a57911591600019045b600182161561238b5792830260801c925b800260801c60028216156123a15792830260801c925b800260801c60048216156123b75792830260801c925b800260801c60088216156123cd5792830260801c925b800260801c60108216156123e35792830260801c925b800260801c60208216156123f95792830260801c925b800260801c604082161561240f5792830260801c925b8002608090811c908216156124265792830260801c925b800260801c61010082161561243d5792830260801c925b800260801c6102008216156124545792830260801c925b800260801c61040082161561246b5792830260801c925b800260801c6108008216156124825792830260801c925b800260801c6110008216156124995792830260801c925b800260801c6120008216156124b05792830260801c925b800260801c6140008216156124c75792830260801c925b800260801c6180008216156124de5792830260801c925b800260801c620100008216156124f65792830260801c925b800260801c6202000082161561250e5792830260801c925b800260801c620400008216156125265792830260801c925b800260801c6208000082161561253e5792830260801c925b505b8260000361256b57604051631dba598d60e11b81526004810186905260248101859052604401610772565b816125765782611e9b565b611e9b83600019612df7565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600081815260018301602052604081205480156126bb5760006125f6600183612d58565b855490915060009061260a90600190612d58565b905080821461266f57600086600001828154811061262a5761262a612d13565b906000526020600020015490508087600001848154811061264d5761264d612d13565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061268057612680612e19565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610626565b6000915050610626565b600081815260028301602052604081208190556115a68383612707565b600081815260018301602052604081205415156115a6565b606060006115a683612713565b60006115a683836125d2565b60608160000180548060200260200160405190810160405280929190818152602001828054801561276357602002820191906000526020600020905b81548152602001906001019080831161274f575b50505050509050919050565b60006020828403121561278157600080fd5b81356001600160e01b0319811681146115a657600080fd5b6020808252825182820181905260009190848201906040850190845b818110156127d1578351835292840192918401916001016127b5565b50909695505050505050565b6000602082840312156127ef57600080fd5b5035919050565b6001600160a01b038116811461152257600080fd5b803561ffff8116811461203157600080fd5b803562ffffff8116811461203157600080fd5b6000806000806000806000806000806101408b8d03121561285057600080fd5b8a3561285b816127f6565b995060208b013561286b816127f6565b985061287960408c0161280b565b975061288760608c0161280b565b965061289560808c0161280b565b95506128a360a08c0161280b565b94506128b160c08c0161280b565b93506128bf60e08c0161281d565b92506128ce6101008c0161280b565b91506128dd6101208c0161281d565b90509295989b9194979a5092959850565b60006020828403121561290057600080fd5b81356115a6816127f6565b60008060006060848603121561292057600080fd5b833561292b816127f6565b9250602084013561293b816127f6565b91506129496040850161280b565b90509250925092565b6000806040838503121561296557600080fd5b823591506020830135612977816127f6565b809150509250929050565b8035801515811461203157600080fd5b60008060008060008060008060006101208a8c0312156129b157600080fd5b6129ba8a61280b565b98506129c860208b0161280b565b97506129d660408b0161280b565b96506129e460608b0161280b565b95506129f260808b0161280b565b9450612a0060a08b0161281d565b9350612a0e60c08b0161280b565b9250612a1c60e08b0161281d565b9150612a2b6101008b01612982565b90509295985092959850929598565b60008060008060008060a08789031215612a5357600080fd5b8635612a5e816127f6565b95506020870135612a6e816127f6565b9450612a7c6040880161280b565b935060608701359250608087013567ffffffffffffffff80821115612aa057600080fd5b818901915089601f830112612ab457600080fd5b813581811115612ac357600080fd5b8a6020828501011115612ad557600080fd5b6020830194508093505050509295509295509295565b60008060408385031215612afe57600080fd5b612b078361280b565b9150612b1560208401612982565b90509250929050565b60008060008060808587031215612b3457600080fd5b8435612b3f816127f6565b93506020850135612b4f816127f6565b9250612b5d6040860161281d565b9150612b6b6060860161280b565b905092959194509250565b60008060408385031215612b8957600080fd5b8235612b94816127f6565b91506020830135612977816127f6565b6020808252825182820181905260009190848201906040850190845b818110156127d157612c0583855161ffff81511682526001600160a01b0360208201511660208301526040810151151560408301526060810151151560608301525050565b9284019260809290920191600101612bc0565b60008060008060808587031215612c2e57600080fd5b8435612c39816127f6565b93506020850135612c49816127f6565b9250612c576040860161280b565b9150612b6b60608601612982565b600080600060608486031215612c7a57600080fd5b8335612c85816127f6565b92506020840135612c95816127f6565b929592945050506040919091013590565b815161ffff1681526020808301516001600160a01b03169082015260408083015115159082015260608083015115159082015260808101610626565b600060208284031215612cf457600080fd5b6115a68261280b565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612d5157612d51612d29565b5060010190565b8181038181111561062657610626612d29565b600060208284031215612d7d57600080fd5b81516115a6816127f6565b600060208284031215612d9a57600080fd5b5051919050565b82815260006020604081840152835180604085015260005b81811015612dd557858101830151858201606001528201612db9565b506000606082860101526060601f19601f830116850101925050509392505050565b600082612e1457634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220ee8dcadda0cd507ffffd4339815ce1787d7e238e4a0303caa9bb6ec910a6d51b64736f6c63430008140033000000000000000000000000e3f132867fc5cbb95d21c53c00647e8e7cd6cf970000000000000000000000004a3723b6e427ecbd90f2848d6df9381a676a02b90000000000000000000000000000000000000000000000000000048c27395000
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061027e5760003560e01c8063701ab8c111610156578063aabc4b3c116100d3578063e203a31f11610097578063e92d0d5d11610071578063e92d0d5d146105c7578063f2fde38b146105da578063fd90c2be146105ed57600080fd5b8063e203a31f14610590578063e30c3978146105a3578063e74b981b146105b457600080fd5b8063aabc4b3c146104f6578063af37106514610546578063b038478114610557578063d547741f1461056a578063ddbfd9411461057d57600080fd5b806380c5061e1161011a57806380c5061e146104b45780638ce9aa1c146104bc5780638da5cb5b146104ca57806391d14854146104db578063a217fddf146104ee57600080fd5b8063701ab8c11461046a578063704037bd14610471578063715018a61461049157806379ba5097146104995780637daf5d66146104a157600080fd5b8063379ee803116101ff5780634e937c3a116101c3578063659ac74b1161019d578063659ac74b146104245780636622e0d71461043757806369d56ea31461045757600080fd5b80634e937c3a146104015780635a440923146104095780635b35875c1461041c57600080fd5b8063379ee803146103a45780633a2f1a91146103b75780633c78a941146103ca5780634ccb20c0146103dd5780634cd161d3146103ee57600080fd5b8063248a9ca311610246578063248a9ca31461033557806327721842146103585780632cc06b8c1461036b5780632f2ff15d1461037e57806336568abe1461039157600080fd5b806301ffc9a7146102835780630282c9c1146102ab5780630752092b146102c0578063093ff769146102eb5780631af5bacc14610300575b600080fd5b61029661029136600461276f565b6105f5565b60405190151581526020015b60405180910390f35b6102b361062c565b6040516102a29190612799565b6102d36102ce3660046127dd565b610706565b6040516001600160a01b0390911681526020016102a2565b6102fe6102f9366004612830565b610713565b005b6103277fdcf4465aa60d92459eb361fac2489220ae3c524301cc0433c30a5d83e8fb0fa981565b6040519081526020016102a2565b6103276103433660046127dd565b60009081526002602052604090206001015490565b6102966103663660046128ee565b610819565b6102fe61037936600461290b565b610826565b6102fe61038c366004612952565b610875565b6102fe61039f366004612952565b61089a565b6102fe6103b2366004612992565b6108d2565b6102fe6103c5366004612a3a565b6109ee565b6102fe6103d83660046128ee565b610aa0565b6003546001600160a01b03166102d3565b6102fe6103fc366004612aeb565b610afe565b600654610327565b6102fe6104173660046128ee565b610bc9565b6102b3610c3b565b6102d3610432366004612b1e565b610c4c565b61044a610445366004612b76565b611174565b6040516102a29190612ba4565b6102fe610465366004612c18565b61130c565b6001610327565b61048461047f366004612c65565b611496565b6040516102a29190612ca6565b6102fe6114cd565b6102fe6114e1565b6102d36104af3660046127dd565b611525565b610327611555565b67016345785d8a0000610327565b6000546001600160a01b03166102d3565b6102966104e9366004612952565b611561565b610327600081565b6105096105043660046127dd565b6115ad565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c0830152151560e0820152610100016102a2565b6005546001600160a01b03166102d3565b6102fe6105653660046128ee565b61166e565b6102fe610578366004612952565b6117af565b6102fe61058b3660046128ee565b6117d4565b6102fe61059e366004612ce2565b611846565b6001546001600160a01b03166102d3565b6102fe6105c23660046128ee565b6118b2565b6102fe6105d53660046127dd565b6118c3565b6102fe6105e83660046128ee565b611966565b600454610327565b60006001600160e01b03198216637965db0b60e01b148061062657506301ffc9a760e01b6001600160e01b03198316145b92915050565b6060600061063a60086119d7565b90508015610702578067ffffffffffffffff81111561065b5761065b612cfd565b604051908082528060200260200182016040528015610684578160200160208202803683370190505b5091506000805b828110156106f3576000806106a16008846119e2565b90925090506106af816119fe565b156106e057818685815181106106c7576106c7612d13565b6020908102919091010152836106dc81612d3f565b9450505b5050806106ec90612d3f565b905061068b565b5081811015610700578083525b505b5090565b6000610626600b83611a0a565b61071b611a16565b600061072c8b8b8b61ffff16611a43565b6020015190506001600160a01b03811661077b5760405163b65ee95360e01b81526001600160a01b03808d1660048301528b16602482015261ffff8a1660448201526064015b60405180910390fd5b604051633329c28d60e11b815261ffff808a16600483015280891660248301528088166044830152808716606483015262ffffff808716608484015290851660a4830152831660c48201526001600160a01b03821690636653851a9060e401600060405180830381600087803b1580156107f457600080fd5b505af1158015610808573d6000803e3d6000fd5b505050505050505050505050505050565b6000610626600b83611aed565b7fdcf4465aa60d92459eb361fac2489220ae3c524301cc0433c30a5d83e8fb0fa961085081611b0f565b6040805160008082526020820190925261086f91869186918691611b19565b50505050565b60008281526002602052604090206001015461089081611b0f565b61086f8383611c60565b6001600160a01b03811633146108c35760405163334bd91960e11b815260040160405180910390fd5b6108cd8282611c8a565b505050565b6108da611a16565b60018961ffff16101561090657604051634f958e7160e01b815261ffff8a166004820152602401610772565b6000610918818a8a8a8a8a8a8a611cff565b905081156109305761092d81600160ff611dff565b90505b610940600861ffff8c1683611e26565b506040805161ffff8b811682528a8116602083015289811682840152888116606083015262ffffff888116608084015287821660a0840152861660c08301529151918c16917f839844a256a87f87c9c835117d9a1c40be013954064c937072acb32d36db6a289181900360e00190a26040518215159061ffff8c16907f58a8b6a02b964cca2712e5a71d7b0d564a56b4a0f573b4c47f389341ade14cfd90600090a350505050505050505050565b7fdcf4465aa60d92459eb361fac2489220ae3c524301cc0433c30a5d83e8fb0fa9610a1881611b0f565b6001600160a01b0384161580610a365750836001600160a01b031916155b15610a545760405163d43a15d160e01b815260040160405180910390fd5b610a978787878787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611b1992505050565b50505050505050565b610aa8611a16565b806001600160a01b031663d3b9fbe46040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ae357600080fd5b505af1158015610af7573d6000803e3d6000fd5b5050505050565b610b06611a16565b610b15600861ffff8416611e33565b610b3857604051637d9160bf60e11b815261ffff83166004820152602401610772565b6000610b49600861ffff8516611e3f565b905081151560ff82901c151503610b73576040516311be38db60e11b815260040160405180910390fd5b610b9061ffff8416610b87838560ff611dff565b60089190611e26565b506040518215159061ffff8516907f58a8b6a02b964cca2712e5a71d7b0d564a56b4a0f573b4c47f389341ade14cfd90600090a3505050565b610bd1611a16565b610bdc600b82611e4b565b610c04576040516303ce0ad960e01b81526001600160a01b0382166004820152602401610772565b6040516001600160a01b038216907f84cc2115995684dcb0cd3d3a9565e3d32f075de81db70c8dc3a719b2a47af67e90600090a250565b6060610c476008611e60565b905090565b6000610c5d600861ffff8416611e33565b610c8057604051637d9160bf60e11b815261ffff83166004820152602401610772565b6000610c91600861ffff8516611e3f565b90506000610ca76000546001600160a01b031690565b6001600160a01b0316336001600160a01b0316149050610cc6826119fe565b158015610cd1575080155b15610cfb576040516304fc2fe760e11b815233600482015261ffff85166024820152604401610772565b610d06600b87611aed565b610d2e57604051638e888ef360e01b81526001600160a01b0387166004820152602401610772565b856001600160a01b0316876001600160a01b031603610d6b57604051632f9b185360e01b81526001600160a01b0388166004820152602401610772565b610d758585611e6d565b50600080610d838989611ea4565b90925090506001600160a01b038216610daf57604051632573cfb960e21b815260040160405180910390fd5b6001600160a01b0382811660009081526007602090815260408083208585168452825280832061ffff8b1684529091529020546201000090041615610e245760405163cb27a43560e01b81526001600160a01b03808b1660048301528916602482015261ffff87166044820152606401610772565b6005546001600160a01b031680610e4e576040516328b4fcf960e21b815260040160405180910390fd5b6040516bffffffffffffffffffffffff1960608c811b821660208401528b901b1660348201527fffff00000000000000000000000000000000000000000000000000000000000060f089901b166048820152610efb908290604a0160408051601f198184030181528282526001600160a01b03808916602085015287169183019190915261ffff8b1660608301529060800160405160208183030381529060405280519060200120611ecd565b6040805160808101825261ffff808b168083526001600160a01b0380861660208086018281528c15158789019081526000606089018181528e8716808352600786528b83208f89168085529087528c84208a855287528c84209b518c549651955193511515600160b81b0260ff60b81b19941515600160b01b029490941661ffff60b01b1996909a16620100000275ffffffffffffffffffffffffffffffffffffffffffff199097169b169a909a179490941792909216959095171790965560068054600181019091557ff652222313e28459528d920b65115c16c04f3efc82aaedc97be59f3f377c0d3f0180546001600160a01b031916909217909155938152600d8452848120928152919092529190912091975061101b9250611f88565b508561ffff16886001600160a01b03168a6001600160a01b03167f2c8d104b27c6b7f4492017a6f5cf3803043688934ebcaa6a03540beeaf976aff8860016006805490506110699190612d58565b604080516001600160a01b03909316835260208301919091520160405180910390a4846001600160a01b03166347973bff6110a386611f94565b6110ac87611fa0565b6110b588611fb0565b6110be89611fc0565b6110c78a611fd0565b6110d08b611fe1565b6110d98c611ff1565b6040516001600160e01b031960e08a901b16815261ffff978816600482015295871660248701529386166044860152918516606485015262ffffff9081166084850152931660a4830152821660c4820152908a1660e482015261010401600060405180830381600087803b15801561115057600080fd5b505af1158015611164573d6000803e3d6000fd5b5050505050505050949350505050565b60606000806111838585611ea4565b6001600160a01b038083166000908152600d6020908152604080832093851683529290529081209294509092506111b982612002565b90508015611302578067ffffffffffffffff8111156111da576111da612cfd565b60405190808252806020026020018201604052801561122c57816020015b6040805160808101825260008082526020808301829052928201819052606082015282526000199092019101816111f85790505b506001600160a01b03808616600090815260076020908152604080832093881683529290529081209196505b828110156112ff57600061127461126f8684611a0a565b61200c565b6040805160808101825261ffff831680825260008181526020888152848220546001600160a01b03620100008204168286015260ff600160b01b8204811615159686019690965292909152879052600160b81b9004909116151560608201528951919250908990849081106112eb576112eb612d13565b602090810291909101015250600101611258565b50505b5050505092915050565b611314611a16565b6000806113218686611ea4565b6001600160a01b0380831660009081526007602090815260408083208486168452825280832061ffff808c1685529083529281902081516080810183529054938416815262010000840490941691840182905260ff600160b01b84048116151591850191909152600160b81b90920490911615156060830152929450909250906113db5760405163102a919160e21b81526001600160a01b0380891660048301528716602482015261ffff86166044820152606401610772565b831515816060015115150361140257604051626ee66560e11b815260040160405180910390fd5b6001600160a01b0380841660009081526007602090815260408083208685168452825280832061ffff8a1684528252918290208054881515600160b81b0260ff60b81b1990911617905583015190519116907f44cf35361c9ff3c8c1397ec6410d5495cc481feaef35c9af11da1a637107de4f9061148590871515815260200190565b60405180910390a250505050505050565b6040805160808101825260008082526020820181905291810182905260608101919091526114c5848484611a43565b949350505050565b6114d5611a16565b6114df6000612036565b565b60015433906001600160a01b031681146115195760405163118cdaa760e01b81526001600160a01b0382166004820152602401610772565b61152281612036565b50565b60006006828154811061153a5761153a612d13565b6000918252602090912001546001600160a01b031692915050565b6000610c47600b612002565b60008261157f57506000546001600160a01b03828116911614610626565b60008381526002602090815260408083206001600160a01b038616845290915290205460ff165b9392505050565b6000808080808080806115c160088a611e33565b6115e157604051637d9160bf60e11b8152600481018a9052602401610772565b60006115ee60088b611e3f565b90506115f981611f94565b61ffff16985061160881611fa0565b61ffff16975061161781611fb0565b61ffff16965061162681611fc0565b61ffff16955061163581611fd0565b62ffffff16945061164581611fe1565b61ffff16935061165481611ff1565b62ffffff16925060ff81901c915050919395975091939597565b611676611a16565b306001600160a01b0316816001600160a01b03166388cc58e46040518163ffffffff1660e01b8152600401602060405180830381865afa1580156116be573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116e29190612d6b565b6001600160a01b03161461171457604051630a3e70af60e11b81526001600160a01b0382166004820152602401610772565b6005546001600160a01b03908116908216810361174f57604051630ded3b9560e31b81526001600160a01b0383166004820152602401610772565b600580546001600160a01b0319166001600160a01b0384811691821790925560408051928416835260208301919091527f900d0e3d359f50e4f923ecdc06b401e07dbb9f485e17b07bcfc91a13000b277e91015b60405180910390a15050565b6000828152600260205260409020600101546117ca81611b0f565b61086f8383611c8a565b6117dc611a16565b6117e7600b8261204f565b61180f57604051638e888ef360e01b81526001600160a01b0382166004820152602401610772565b6040516001600160a01b038216907f0b767739217755d8af5a2ba75b181a19fa1750f8bb701f09311cb19a90140cb390600090a250565b61184e611a16565b61185d600861ffff8316612064565b61188057604051637d9160bf60e11b815261ffff82166004820152602401610772565b60405161ffff8216907fdd86b848bb56ff540caa68683fa467d0e7eb5f8b2d44e4ee435742eeeae9be1390600090a250565b6118ba611a16565b61152281612070565b6118cb611a16565b6004548181036118f157604051631baa31e960e21b815260048101839052602401610772565b67016345785d8a000082111561192b57604051635e8988c160e01b81526004810183905267016345785d8a00006024820152604401610772565b600482905560408051828152602081018490527f5c34e91c94c78b662a45d0bd4a25a4e32c584c54a45a76e4a4d43be27ba40e5091016117a3565b61196e611a16565b600180546001600160a01b0383166001600160a01b0319909116811790915561199f6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60006106268261212e565b60008080806119f18686612139565b9097909650945050505050565b600060ff82901c610626565b60006115a68383612164565b6000546001600160a01b031633146114df5760405163118cdaa760e01b8152336004820152602401610772565b604080516080810182526000808252602082018190529181018290526060810191909152611a718484611ea4565b6001600160a01b03918216600090815260076020908152604080832093851683529281528282209582529485528190208151608081018352905461ffff811682526201000081049093169481019490945260ff600160b01b83048116151591850191909152600160b81b90910416151560608301525092915050565b6001600160a01b038116600090815260018301602052604081205415156115a6565b611522813361218e565b6000611b2a86868661ffff16611a43565b6020015190506001600160a01b038116611b745760405163b65ee95360e01b81526001600160a01b0380881660048301528616602482015261ffff85166044820152606401610772565b82816001600160a01b031663781a89156040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd79190612d88565b03611bf85760405163b70cd0db60e01b815260048101849052602401610772565b604051631b057f6d60e01b81526001600160a01b03821690631b057f6d90611c269086908690600401612da1565b600060405180830381600087803b158015611c4057600080fd5b505af1158015611c54573d6000803e3d6000fd5b50505050505050505050565b600082611c8057604051633e3253cf60e11b815260040160405180910390fd5b6115a683836121cb565b6000611c968383611561565b15611cf75760008381526002602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a4506001610626565b506000610626565b60008561ffff168761ffff161180611d1c5750610fff8661ffff16115b80611d2c57506127108561ffff16115b80611d3c57506109c48361ffff16115b80611d4e5750620fffff8262ffffff16115b15611d6c57604051631c07203f60e01b815260040160405180910390fd5b5060109590951b630fff00001661ffff9690961695909517601c9390931b64fff0000000169290921760289190911b663fff0000000000161760369190911b693fffffc00000000000001617604e9290921b6b0fffc00000000000000000001691909117605c9190911b6dfffff0000000000000000000000016176dffffffffffffffffffffffffffff19919091161790565b60006114c58484611e11576000611e14565b60015b600180861b19929092169116841b1790565b60006114c5848484612257565b60006115a68383612274565b60006115a68383612280565b60006115a6836001600160a01b0384166122c7565b606060006115a68361230e565b600061271061ffff60801b608084901b1604600160801b0162ffffff8416627fffff1901611e9b8282612319565b95945050505050565b600080826001600160a01b0316846001600160a01b03161115611ec5579192915b509192909150565b600060408303516020840351845180602087010180516002830161ffca811115611eff5763c8c781396000526004601cfd5b6c5af43d3d93803e603357fd5bf3895289600d8a03527d6100003d81600a3d39f3363d3d373d3d3d3d610000806035363936013d738160481b176035820160d81b1760218a03528060f01b835287603f8201601f8b036000f596505085611f6e5763301164256000526004601cfd5b90528552601f19850152603f199093019290925250919050565b60006115a683836122c7565b600061ffff8216610626565b60006106268260101c610fff1690565b600061062682601c1c610fff1690565b60006106268260281c613fff1690565b60006106268260361c62ffffff1690565b600061062682604e1c613fff1690565b600061062682605c1c620fffff1690565b6000610626825490565b8061ffff81168114612031576040516364ae406d60e01b815260040160405180910390fd5b919050565b600180546001600160a01b031916905561152281612582565b60006115a6836001600160a01b0384166125d2565b60006115a683836126c5565b6001600160a01b03811661209757604051632573cfb960e21b815260040160405180910390fd5b6003546001600160a01b0390811690821681036120d657600354604051634fcea97160e01b81526001600160a01b039091166004820152602401610772565b600380546001600160a01b0319166001600160a01b0384811691821790925560408051928416835260208301919091527f15d80a013f22151bc7246e3bc132e12828cde19de98870475e3fa7084015272191016117a3565b600061062682612002565b600080806121478585611a0a565b600081815260029690960160205260409095205494959350505050565b600082600001828154811061217b5761217b612d13565b9060005260206000200154905092915050565b6121988282611561565b6121c75760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610772565b5050565b60006121d78383611561565b611cf75760008381526002602090815260408083206001600160a01b03861684529091529020805460ff1916600117905561220f3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610626565b600082815260028401602052604081208290556114c58484611f88565b60006115a683836126e2565b6000818152600283016020526040812054801580156122a657506122a48484612274565b155b156115a65760405163015ab34360e11b815260048101849052602401610772565b6000818152600183016020526040812054611cf757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610626565b6060610626826126fa565b6000806000836000036123355750600160801b91506106269050565b50826000811215612347579015906000035b6210000081101561254057600160801b9250846fffffffffffffffffffffffffffffffff81111561237a57911591600019045b600182161561238b5792830260801c925b800260801c60028216156123a15792830260801c925b800260801c60048216156123b75792830260801c925b800260801c60088216156123cd5792830260801c925b800260801c60108216156123e35792830260801c925b800260801c60208216156123f95792830260801c925b800260801c604082161561240f5792830260801c925b8002608090811c908216156124265792830260801c925b800260801c61010082161561243d5792830260801c925b800260801c6102008216156124545792830260801c925b800260801c61040082161561246b5792830260801c925b800260801c6108008216156124825792830260801c925b800260801c6110008216156124995792830260801c925b800260801c6120008216156124b05792830260801c925b800260801c6140008216156124c75792830260801c925b800260801c6180008216156124de5792830260801c925b800260801c620100008216156124f65792830260801c925b800260801c6202000082161561250e5792830260801c925b800260801c620400008216156125265792830260801c925b800260801c6208000082161561253e5792830260801c925b505b8260000361256b57604051631dba598d60e11b81526004810186905260248101859052604401610772565b816125765782611e9b565b611e9b83600019612df7565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600081815260018301602052604081205480156126bb5760006125f6600183612d58565b855490915060009061260a90600190612d58565b905080821461266f57600086600001828154811061262a5761262a612d13565b906000526020600020015490508087600001848154811061264d5761264d612d13565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061268057612680612e19565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610626565b6000915050610626565b600081815260028301602052604081208190556115a68383612707565b600081815260018301602052604081205415156115a6565b606060006115a683612713565b60006115a683836125d2565b60608160000180548060200260200160405190810160405280929190818152602001828054801561276357602002820191906000526020600020905b81548152602001906001019080831161274f575b50505050509050919050565b60006020828403121561278157600080fd5b81356001600160e01b0319811681146115a657600080fd5b6020808252825182820181905260009190848201906040850190845b818110156127d1578351835292840192918401916001016127b5565b50909695505050505050565b6000602082840312156127ef57600080fd5b5035919050565b6001600160a01b038116811461152257600080fd5b803561ffff8116811461203157600080fd5b803562ffffff8116811461203157600080fd5b6000806000806000806000806000806101408b8d03121561285057600080fd5b8a3561285b816127f6565b995060208b013561286b816127f6565b985061287960408c0161280b565b975061288760608c0161280b565b965061289560808c0161280b565b95506128a360a08c0161280b565b94506128b160c08c0161280b565b93506128bf60e08c0161281d565b92506128ce6101008c0161280b565b91506128dd6101208c0161281d565b90509295989b9194979a5092959850565b60006020828403121561290057600080fd5b81356115a6816127f6565b60008060006060848603121561292057600080fd5b833561292b816127f6565b9250602084013561293b816127f6565b91506129496040850161280b565b90509250925092565b6000806040838503121561296557600080fd5b823591506020830135612977816127f6565b809150509250929050565b8035801515811461203157600080fd5b60008060008060008060008060006101208a8c0312156129b157600080fd5b6129ba8a61280b565b98506129c860208b0161280b565b97506129d660408b0161280b565b96506129e460608b0161280b565b95506129f260808b0161280b565b9450612a0060a08b0161281d565b9350612a0e60c08b0161280b565b9250612a1c60e08b0161281d565b9150612a2b6101008b01612982565b90509295985092959850929598565b60008060008060008060a08789031215612a5357600080fd5b8635612a5e816127f6565b95506020870135612a6e816127f6565b9450612a7c6040880161280b565b935060608701359250608087013567ffffffffffffffff80821115612aa057600080fd5b818901915089601f830112612ab457600080fd5b813581811115612ac357600080fd5b8a6020828501011115612ad557600080fd5b6020830194508093505050509295509295509295565b60008060408385031215612afe57600080fd5b612b078361280b565b9150612b1560208401612982565b90509250929050565b60008060008060808587031215612b3457600080fd5b8435612b3f816127f6565b93506020850135612b4f816127f6565b9250612b5d6040860161281d565b9150612b6b6060860161280b565b905092959194509250565b60008060408385031215612b8957600080fd5b8235612b94816127f6565b91506020830135612977816127f6565b6020808252825182820181905260009190848201906040850190845b818110156127d157612c0583855161ffff81511682526001600160a01b0360208201511660208301526040810151151560408301526060810151151560608301525050565b9284019260809290920191600101612bc0565b60008060008060808587031215612c2e57600080fd5b8435612c39816127f6565b93506020850135612c49816127f6565b9250612c576040860161280b565b9150612b6b60608601612982565b600080600060608486031215612c7a57600080fd5b8335612c85816127f6565b92506020840135612c95816127f6565b929592945050506040919091013590565b815161ffff1681526020808301516001600160a01b03169082015260408083015115159082015260608083015115159082015260808101610626565b600060208284031215612cf457600080fd5b6115a68261280b565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201612d5157612d51612d29565b5060010190565b8181038181111561062657610626612d29565b600060208284031215612d7d57600080fd5b81516115a6816127f6565b600060208284031215612d9a57600080fd5b5051919050565b82815260006020604081840152835180604085015260005b81811015612dd557858101830151858201606001528201612db9565b506000606082860101526060601f19601f830116850101925050509392505050565b600082612e1457634e487b7160e01b600052601260045260246000fd5b500490565b634e487b7160e01b600052603160045260246000fdfea2646970667358221220ee8dcadda0cd507ffffd4339815ce1787d7e238e4a0303caa9bb6ec910a6d51b64736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000e3f132867fc5cbb95d21c53c00647e8e7cd6cf970000000000000000000000004a3723b6e427ecbd90f2848d6df9381a676a02b90000000000000000000000000000000000000000000000000000048c27395000
-----Decoded View---------------
Arg [0] : feeRecipient (address): 0xE3F132867fC5cbb95D21C53c00647E8e7Cd6CF97
Arg [1] : initialOwner (address): 0x4A3723B6e427Ecbd90f2848d6dF9381A676a02b9
Arg [2] : flashLoanFee (uint256): 5000000000000
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000e3f132867fc5cbb95d21c53c00647e8e7cd6cf97
Arg [1] : 0000000000000000000000004a3723b6e427ecbd90f2848d6df9381a676a02b9
Arg [2] : 0000000000000000000000000000000000000000000000000000048c27395000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.