Overview
AVAX Balance
AVAX Value
$0.00Latest 9 from a total of 9 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Set Pending Owne... | 22427077 | 1089 days ago | IN | 0 AVAX | 0.00125697 | ||||
| Set Preset | 22426958 | 1089 days ago | IN | 0 AVAX | 0.00162276 | ||||
| Set Preset | 22426958 | 1089 days ago | IN | 0 AVAX | 0.00162276 | ||||
| Set Preset | 22426958 | 1089 days ago | IN | 0 AVAX | 0.00162276 | ||||
| Set Preset | 22426958 | 1089 days ago | IN | 0 AVAX | 0.0016231 | ||||
| Set Preset | 22426958 | 1089 days ago | IN | 0 AVAX | 0.00162276 | ||||
| Set Preset | 22426958 | 1089 days ago | IN | 0 AVAX | 0.00210381 | ||||
| Add Quote Asset | 22426956 | 1089 days ago | IN | 0 AVAX | 0.00257446 | ||||
| Set LB Pair Impl... | 22426956 | 1089 days ago | IN | 0 AVAX | 0.00142553 |
Latest 25 internal transactions (View All)
Cross-Chain Transactions
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.10+commit.fc410830
Optimization Enabled:
Yes with 800 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "openzeppelin/proxy/Clones.sol";
import "openzeppelin/utils/structs/EnumerableSet.sol";
import "./LBErrors.sol";
import "./libraries/BinHelper.sol";
import "./libraries/Constants.sol";
import "./libraries/Decoder.sol";
import "./libraries/PendingOwnable.sol";
import "./libraries/SafeCast.sol";
import "./interfaces/ILBFactory.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 `creationUnlocked` is `true`, only the owner of the factory can create pairs.
contract LBFactory is PendingOwnable, ILBFactory {
using SafeCast for uint256;
using Decoder for bytes32;
using EnumerableSet for EnumerableSet.AddressSet;
uint256 public constant override MAX_FEE = 0.1e18; // 10%
uint256 public constant override MIN_BIN_STEP = 1; // 0.01%
uint256 public constant override MAX_BIN_STEP = 100; // 1%, can't be greater than 247 for indexing reasons
uint256 public constant override MAX_PROTOCOL_SHARE = 2_500; // 25%
address public override LBPairImplementation;
address public override feeRecipient;
/// @notice Whether the createLBPair function is unlocked and can be called by anyone (true) or only by owner (false)
bool public override creationUnlocked;
uint256 public override flashLoanFee;
ILBPair[] public override 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;
/// @dev Whether a preset was set or not, if the bit at `index` is 1, it means that the binStep `index` was set
/// The max binStep set is 247. We use this method instead of an array to keep it ordered and to reduce gas
bytes32 private _availablePresets;
// The parameters presets
mapping(uint256 => bytes32) private _presets;
EnumerableSet.AddressSet private _quoteAssetWhitelist;
/// @dev Whether a LBPair was created with a bin step, if the bit at `index` is 1, it means that the LBPair with binStep `index` exists
/// The max binStep set is 247. We use this method instead of an array to keep it ordered and to reduce gas
mapping(IERC20 => mapping(IERC20 => bytes32)) 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, uint256 _flashLoanFee) {
if (_flashLoanFee > MAX_FEE) revert LBFactory__FlashLoanFeeAboveMax(_flashLoanFee, MAX_FEE);
_setFeeRecipient(_feeRecipient);
flashLoanFee = _flashLoanFee;
emit FlashLoanFeeSet(0, _flashLoanFee);
}
/// @notice View function to return the number of LBPairs created
/// @return The number of LBPair
function getNumberOfLBPairs() external view override returns (uint256) {
return allLBPairs.length;
}
/// @notice View function to return the number of quote assets whitelisted
/// @return The number of quote assets
function getNumberOfQuoteAssets() external view override returns (uint256) {
return _quoteAssetWhitelist.length();
}
/// @notice View function to return the quote asset whitelisted at index `index`
/// @param _index The index
/// @return The address of the _quoteAsset at index `index`
function getQuoteAsset(uint256 _index) external view override returns (IERC20) {
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 Whether the token is a quote asset or not
function isQuoteAsset(IERC20 _token) external view override returns (bool) {
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 The LBPairInformation
function getLBPairInformation(
IERC20 _tokenA,
IERC20 _tokenB,
uint256 _binStep
) external view override returns (LBPairInformation memory) {
return _getLBPairInformation(_tokenA, _tokenB, _binStep);
}
/// @notice View function to return the different parameters of the preset
/// @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 maxVolatilityAccumulated The max volatility accumulated of the preset
/// @return sampleLifetime The sample lifetime of the preset
function getPreset(uint16 _binStep)
external
view
override
returns (
uint256 baseFactor,
uint256 filterPeriod,
uint256 decayPeriod,
uint256 reductionFactor,
uint256 variableFeeControl,
uint256 protocolShare,
uint256 maxVolatilityAccumulated,
uint256 sampleLifetime
)
{
bytes32 _preset = _presets[_binStep];
if (_preset == bytes32(0)) revert LBFactory__BinStepHasNoPreset(_binStep);
uint256 _shift;
// Safety check
require(_binStep == _preset.decode(type(uint16).max, _shift));
baseFactor = _preset.decode(type(uint16).max, _shift += 16);
filterPeriod = _preset.decode(type(uint16).max, _shift += 16);
decayPeriod = _preset.decode(type(uint16).max, _shift += 16);
reductionFactor = _preset.decode(type(uint16).max, _shift += 16);
variableFeeControl = _preset.decode(type(uint24).max, _shift += 16);
protocolShare = _preset.decode(type(uint16).max, _shift += 24);
maxVolatilityAccumulated = _preset.decode(type(uint24).max, _shift += 16);
sampleLifetime = _preset.decode(type(uint16).max, 240);
}
/// @notice View function to return the list of available binStep with a preset
/// @return presetsBinStep The list of binStep
function getAllBinSteps() external view override returns (uint256[] memory presetsBinStep) {
unchecked {
bytes32 _avPresets = _availablePresets;
uint256 _nbPresets = _avPresets.decode(type(uint8).max, 248);
if (_nbPresets > 0) {
presetsBinStep = new uint256[](_nbPresets);
uint256 _index;
for (uint256 i = MIN_BIN_STEP; i <= MAX_BIN_STEP; ++i) {
if (_avPresets.decode(1, i) == 1) {
presetsBinStep[_index] = i;
if (++_index == _nbPresets) break;
}
}
}
}
}
/// @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);
bytes32 _avLBPairBinSteps = _availableLBPairBinSteps[_tokenA][_tokenB];
uint256 _nbAvailable = _avLBPairBinSteps.decode(type(uint8).max, 248);
if (_nbAvailable > 0) {
LBPairsAvailable = new LBPairInformation[](_nbAvailable);
uint256 _index;
for (uint256 i = MIN_BIN_STEP; i <= MAX_BIN_STEP; ++i) {
if (_avLBPairBinSteps.decode(1, i) == 1) {
LBPairInformation memory _LBPairInformation = _LBPairsInfo[_tokenA][_tokenB][i];
LBPairsAvailable[_index] = LBPairInformation({
binStep: i.safe16(),
LBPair: _LBPairInformation.LBPair,
createdByOwner: _LBPairInformation.createdByOwner,
ignoredForRouting: _LBPairInformation.ignoredForRouting
});
if (++_index == _nbAvailable) break;
}
}
}
}
}
/// @notice Set the LBPair implementation address
/// @dev Needs to be called by the owner
/// @param _LBPairImplementation The address of the implementation
function setLBPairImplementation(address _LBPairImplementation) external override onlyOwner {
if (ILBPair(_LBPairImplementation).factory() != this)
revert LBFactory__LBPairSafetyCheckFailed(_LBPairImplementation);
address _oldLBPairImplementation = LBPairImplementation;
if (_oldLBPairImplementation == _LBPairImplementation)
revert LBFactory__SameImplementation(_LBPairImplementation);
LBPairImplementation = _LBPairImplementation;
emit LBPairImplementationSet(_oldLBPairImplementation, _LBPairImplementation);
}
/// @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)
/// @return _LBPair The address of the newly created LBPair
function createLBPair(
IERC20 _tokenX,
IERC20 _tokenY,
uint24 _activeId,
uint16 _binStep
) external override returns (ILBPair _LBPair) {
address _owner = owner();
if (!creationUnlocked && msg.sender != _owner) revert LBFactory__FunctionIsLockedForUsers(msg.sender);
address _LBPairImplementation = LBPairImplementation;
if (_LBPairImplementation == address(0)) revert LBFactory__ImplementationNotSet();
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
BinHelper.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);
bytes32 _preset = _presets[_binStep];
if (_preset == bytes32(0)) revert LBFactory__BinStepHasNoPreset(_binStep);
uint256 _sampleLifetime = _preset.decode(type(uint16).max, 240);
// We remove the bits that are not part of the feeParameters
_preset &= bytes32(uint256(type(uint144).max));
bytes32 _salt = keccak256(abi.encode(_tokenA, _tokenB, _binStep));
_LBPair = ILBPair(Clones.cloneDeterministic(_LBPairImplementation, _salt));
_LBPair.initialize(_tokenX, _tokenY, _activeId, uint16(_sampleLifetime), _preset);
_LBPairsInfo[_tokenA][_tokenB][_binStep] = LBPairInformation({
binStep: _binStep,
LBPair: _LBPair,
createdByOwner: msg.sender == _owner,
ignoredForRouting: false
});
allLBPairs.push(_LBPair);
{
bytes32 _avLBPairBinSteps = _availableLBPairBinSteps[_tokenA][_tokenB];
// We add a 1 at bit `_binStep` as this binStep is now set
_avLBPairBinSteps = bytes32(uint256(_avLBPairBinSteps) | (1 << _binStep));
// Increase the number of lb pairs by 1
_avLBPairBinSteps = bytes32(uint256(_avLBPairBinSteps) + (1 << 248));
// Save the changes
_availableLBPairBinSteps[_tokenA][_tokenB] = _avLBPairBinSteps;
}
emit LBPairCreated(_tokenX, _tokenY, _binStep, _LBPair, allLBPairs.length - 1);
emit FeeParametersSet(
msg.sender,
_LBPair,
_binStep,
_preset.decode(type(uint16).max, 16),
_preset.decode(type(uint16).max, 32),
_preset.decode(type(uint16).max, 48),
_preset.decode(type(uint16).max, 64),
_preset.decode(type(uint24).max, 80),
_preset.decode(type(uint16).max, 104),
_preset.decode(type(uint24).max, 120)
);
}
/// @notice Function to set whether the pair is ignored or not for routing, it will make the pair unusable by the router
/// @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,
uint256 _binStep,
bool _ignored
) external override onlyOwner {
(IERC20 _tokenA, IERC20 _tokenB) = _sortTokens(_tokenX, _tokenY);
LBPairInformation memory _LBPairInformation = _LBPairsInfo[_tokenA][_tokenB][_binStep];
if (address(_LBPairInformation.LBPair) == address(0)) revert LBFactory__AddressZero();
if (_LBPairInformation.ignoredForRouting == _ignored) revert LBFactory__LBPairIgnoredIsAlreadyInTheSameState();
_LBPairsInfo[_tokenA][_tokenB][_binStep].ignoredForRouting = _ignored;
emit LBPairIgnoredStateChanged(_LBPairInformation.LBPair, _ignored);
}
/// @notice Sets the preset parameters of a bin step
/// @param _binStep The bin step in basis point, used to calculate log(1 + binStep)
/// @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 halved
/// @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 _maxVolatilityAccumulated The max value of the volatility accumulated
/// @param _sampleLifetime The lifetime of an oracle's sample
function setPreset(
uint16 _binStep,
uint16 _baseFactor,
uint16 _filterPeriod,
uint16 _decayPeriod,
uint16 _reductionFactor,
uint24 _variableFeeControl,
uint16 _protocolShare,
uint24 _maxVolatilityAccumulated,
uint16 _sampleLifetime
) external override onlyOwner {
bytes32 _packedFeeParameters = _getPackedFeeParameters(
_binStep,
_baseFactor,
_filterPeriod,
_decayPeriod,
_reductionFactor,
_variableFeeControl,
_protocolShare,
_maxVolatilityAccumulated
);
// The last 16 bits are reserved for sampleLifetime
bytes32 _preset = bytes32(
(uint256(_packedFeeParameters) & type(uint144).max) | (uint256(_sampleLifetime) << 240)
);
_presets[_binStep] = _preset;
bytes32 _avPresets = _availablePresets;
if (_avPresets.decode(1, _binStep) == 0) {
// We add a 1 at bit `_binStep` as this binStep is now set
_avPresets = bytes32(uint256(_avPresets) | (1 << _binStep));
// Increase the number of preset by 1
_avPresets = bytes32(uint256(_avPresets) + (1 << 248));
// Save the changes
_availablePresets = _avPresets;
}
emit PresetSet(
_binStep,
_baseFactor,
_filterPeriod,
_decayPeriod,
_reductionFactor,
_variableFeeControl,
_protocolShare,
_maxVolatilityAccumulated,
_sampleLifetime
);
}
/// @notice Remove the preset linked to a binStep
/// @param _binStep The bin step to remove
function removePreset(uint16 _binStep) external override onlyOwner {
if (_presets[_binStep] == bytes32(0)) revert LBFactory__BinStepHasNoPreset(_binStep);
// Set the bit `_binStep` to 0
bytes32 _avPresets = _availablePresets;
_avPresets &= bytes32(type(uint256).max - (1 << _binStep));
_avPresets = bytes32(uint256(_avPresets) - (1 << 248));
// Save the changes
_availablePresets = _avPresets;
delete _presets[_binStep];
emit PresetRemoved(_binStep);
}
/// @notice Function to set the fee parameter of a LBPair
/// @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 log(1 + binStep)
/// @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 halved
/// @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 _maxVolatilityAccumulated The max value of volatility accumulated
function setFeesParametersOnPair(
IERC20 _tokenX,
IERC20 _tokenY,
uint16 _binStep,
uint16 _baseFactor,
uint16 _filterPeriod,
uint16 _decayPeriod,
uint16 _reductionFactor,
uint24 _variableFeeControl,
uint16 _protocolShare,
uint24 _maxVolatilityAccumulated
) external override onlyOwner {
ILBPair _LBPair = _getLBPairInformation(_tokenX, _tokenY, _binStep).LBPair;
if (address(_LBPair) == address(0)) revert LBFactory__LBPairNotCreated(_tokenX, _tokenY, _binStep);
bytes32 _packedFeeParameters = _getPackedFeeParameters(
_binStep,
_baseFactor,
_filterPeriod,
_decayPeriod,
_reductionFactor,
_variableFeeControl,
_protocolShare,
_maxVolatilityAccumulated
);
_LBPair.setFeesParameters(_packedFeeParameters);
emit FeeParametersSet(
msg.sender,
_LBPair,
_binStep,
_baseFactor,
_filterPeriod,
_decayPeriod,
_reductionFactor,
_variableFeeControl,
_protocolShare,
_maxVolatilityAccumulated
);
}
/// @notice Function to set the recipient of the fees. This address needs to be able to receive ERC20s
/// @param _feeRecipient The address of the recipient
function setFeeRecipient(address _feeRecipient) external override onlyOwner {
_setFeeRecipient(_feeRecipient);
}
/// @notice Function to set the 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_FEE) revert LBFactory__FlashLoanFeeAboveMax(_flashLoanFee, MAX_FEE);
flashLoanFee = _flashLoanFee;
emit FlashLoanFeeSet(_oldFlashLoanFee, _flashLoanFee);
}
/// @notice Function to set the creation restriction of the Factory
/// @param _locked If the creation is restricted (true) or not (false)
function setFactoryLockedState(bool _locked) external override onlyOwner {
if (creationUnlocked != _locked) revert LBFactory__FactoryLockIsAlreadyInTheSameState();
creationUnlocked = !_locked;
emit FactoryLockedStatusUpdated(_locked);
}
/// @notice Function to add an asset to the whitelist of quote assets
/// @param _quoteAsset The quote asset (e.g: AVAX, 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
/// @param _quoteAsset The quote asset (e.g: AVAX, USDC...)
function removeQuoteAsset(IERC20 _quoteAsset) external override onlyOwner {
if (!_quoteAssetWhitelist.remove(address(_quoteAsset))) revert LBFactory__QuoteAssetNotWhitelisted(_quoteAsset);
emit QuoteAssetRemoved(_quoteAsset);
}
/// @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);
}
function forceDecay(ILBPair _LBPair) external override onlyOwner {
_LBPair.forceDecay();
}
/// @notice Internal function to set the fee parameter of a LBPair
/// @param _binStep The bin step in basis point, used to calculate log(1 + binStep)
/// @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 halved
/// @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 _maxVolatilityAccumulated The max value of volatility accumulated
function _getPackedFeeParameters(
uint16 _binStep,
uint16 _baseFactor,
uint16 _filterPeriod,
uint16 _decayPeriod,
uint16 _reductionFactor,
uint24 _variableFeeControl,
uint16 _protocolShare,
uint24 _maxVolatilityAccumulated
) private pure returns (bytes32) {
if (_binStep < MIN_BIN_STEP || _binStep > MAX_BIN_STEP)
revert LBFactory__BinStepRequirementsBreached(MIN_BIN_STEP, _binStep, MAX_BIN_STEP);
if (_filterPeriod >= _decayPeriod) revert LBFactory__DecreasingPeriods(_filterPeriod, _decayPeriod);
if (_reductionFactor > Constants.BASIS_POINT_MAX)
revert LBFactory__ReductionFactorOverflows(_reductionFactor, Constants.BASIS_POINT_MAX);
if (_protocolShare > MAX_PROTOCOL_SHARE)
revert LBFactory__ProtocolShareOverflows(_protocolShare, MAX_PROTOCOL_SHARE);
{
uint256 _baseFee = (uint256(_baseFactor) * _binStep) * 1e10;
// Can't overflow as the max value is `max(uint24) * (max(uint24) * max(uint16)) ** 2 < max(uint104)`
// It returns 18 decimals as:
// decimals(variableFeeControl * (volatilityAccumulated * binStep)**2 / 100) = 4 + (4 + 4) * 2 - 2 = 18
uint256 _prod = uint256(_maxVolatilityAccumulated) * _binStep;
uint256 _maxVariableFee = (_prod * _prod * _variableFeeControl) / 100;
if (_baseFee + _maxVariableFee > MAX_FEE)
revert LBFactory__FeesAboveMax(_baseFee + _maxVariableFee, MAX_FEE);
}
/// @dev It's very important that the sum of the sizes of those values is exactly 256 bits
/// here, (112 + 24) + 16 + 24 + 16 + 16 + 16 + 16 + 16 = 256
return
bytes32(
abi.encodePacked(
uint136(_maxVolatilityAccumulated), // The first 112 bits are reserved for the dynamic parameters
_protocolShare,
_variableFeeControl,
_reductionFactor,
_decayPeriod,
_filterPeriod,
_baseFactor,
_binStep
)
);
}
/// @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);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/Clones.sol)
pragma solidity ^0.8.0;
/**
* @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for
* deploying minimal proxy contracts, also known as "clones".
*
* > To simply and cheaply clone contract functionality in an immutable way, this standard specifies
* > a minimal bytecode implementation that delegates all calls to a known, fixed address.
*
* The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2`
* (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the
* deterministic method.
*
* _Available since v3.4._
*/
library Clones {
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create opcode, which should never revert.
*/
function clone(address implementation) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create(0, ptr, 0x37)
}
require(instance != address(0), "ERC1167: create failed");
}
/**
* @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`.
*
* This function uses the create2 opcode and a `salt` to deterministically deploy
* the clone. Using the same `implementation` and `salt` multiple time will revert, since
* the clones cannot be deployed twice at the same address.
*/
function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf30000000000000000000000000000000000)
instance := create2(0, ptr, 0x37, salt)
}
require(instance != address(0), "ERC1167: create2 failed");
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(
address implementation,
bytes32 salt,
address deployer
) internal pure returns (address predicted) {
/// @solidity memory-safe-assembly
assembly {
let ptr := mload(0x40)
mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000000000000000000000)
mstore(add(ptr, 0x14), shl(0x60, implementation))
mstore(add(ptr, 0x28), 0x5af43d82803e903d91602b57fd5bf3ff00000000000000000000000000000000)
mstore(add(ptr, 0x38), shl(0x60, deployer))
mstore(add(ptr, 0x4c), salt)
mstore(add(ptr, 0x6c), keccak256(ptr, 0x37))
predicted := keccak256(add(ptr, 0x37), 0x55)
}
}
/**
* @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}.
*/
function predictDeterministicAddress(address implementation, bytes32 salt)
internal
view
returns (address predicted)
{
return predictDeterministicAddress(implementation, salt, address(this));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` 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 amount
) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (utils/structs/EnumerableSet.sol)
pragma solidity ^0.8.0;
/**
* @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.
*
* ```
* 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 of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping(bytes32 => uint256) _indexes;
}
/**
* @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._indexes[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 read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 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 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastValue;
// Update the index for the moved value
set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[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._indexes[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) {
return _values(set._inner);
}
// 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 on 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
pragma solidity 0.8.10;
import "./interfaces/ILBPair.sol";
/** LBRouter errors */
error LBRouter__SenderIsNotWAVAX();
error LBRouter__PairNotCreated(address tokenX, address tokenY, uint256 binStep);
error LBRouter__WrongAmounts(uint256 amount, uint256 reserve);
error LBRouter__SwapOverflows(uint256 id);
error LBRouter__BrokenSwapSafetyCheck();
error LBRouter__NotFactoryOwner();
error LBRouter__TooMuchTokensIn(uint256 excess);
error LBRouter__BinReserveOverflows(uint256 id);
error LBRouter__IdOverflows(int256 id);
error LBRouter__LengthsMismatch();
error LBRouter__WrongTokenOrder();
error LBRouter__IdSlippageCaught(uint256 activeIdDesired, uint256 idSlippage, uint256 activeId);
error LBRouter__AmountSlippageCaught(uint256 amountXMin, uint256 amountX, uint256 amountYMin, uint256 amountY);
error LBRouter__IdDesiredOverflows(uint256 idDesired, uint256 idSlippage);
error LBRouter__FailedToSendAVAX(address recipient, uint256 amount);
error LBRouter__DeadlineExceeded(uint256 deadline, uint256 currentTimestamp);
error LBRouter__AmountSlippageBPTooBig(uint256 amountSlippage);
error LBRouter__InsufficientAmountOut(uint256 amountOutMin, uint256 amountOut);
error LBRouter__MaxAmountInExceeded(uint256 amountInMax, uint256 amountIn);
error LBRouter__InvalidTokenPath(address wrongToken);
error LBRouter__InvalidVersion(uint256 version);
error LBRouter__WrongAvaxLiquidityParameters(
address tokenX,
address tokenY,
uint256 amountX,
uint256 amountY,
uint256 msgValue
);
/** LBToken errors */
error LBToken__SpenderNotApproved(address owner, address spender);
error LBToken__TransferFromOrToAddress0();
error LBToken__MintToAddress0();
error LBToken__BurnFromAddress0();
error LBToken__BurnExceedsBalance(address from, uint256 id, uint256 amount);
error LBToken__LengthMismatch(uint256 accountsLength, uint256 idsLength);
error LBToken__SelfApproval(address owner);
error LBToken__TransferExceedsBalance(address from, uint256 id, uint256 amount);
error LBToken__TransferToSelf();
/** LBFactory errors */
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__LBPairNotCreated(IERC20 tokenX, IERC20 tokenY, uint256 binStep);
error LBFactory__DecreasingPeriods(uint16 filterPeriod, uint16 decayPeriod);
error LBFactory__ReductionFactorOverflows(uint16 reductionFactor, uint256 max);
error LBFactory__VariableFeeControlOverflows(uint16 variableFeeControl, uint256 max);
error LBFactory__BaseFeesBelowMin(uint256 baseFees, uint256 minBaseFees);
error LBFactory__FeesAboveMax(uint256 fees, uint256 maxFees);
error LBFactory__FlashLoanFeeAboveMax(uint256 fees, uint256 maxFees);
error LBFactory__BinStepRequirementsBreached(uint256 lowerBound, uint16 binStep, uint256 higherBound);
error LBFactory__ProtocolShareOverflows(uint16 protocolShare, uint256 max);
error LBFactory__FunctionIsLockedForUsers(address user);
error LBFactory__FactoryLockIsAlreadyInTheSameState();
error LBFactory__LBPairIgnoredIsAlreadyInTheSameState();
error LBFactory__BinStepHasNoPreset(uint256 binStep);
error LBFactory__SameFeeRecipient(address feeRecipient);
error LBFactory__SameFlashLoanFee(uint256 flashLoanFee);
error LBFactory__LBPairSafetyCheckFailed(address LBPairImplementation);
error LBFactory__SameImplementation(address LBPairImplementation);
error LBFactory__ImplementationNotSet();
/** LBPair errors */
error LBPair__InsufficientAmounts();
error LBPair__AddressZero();
error LBPair__AddressZeroOrThis();
error LBPair__CompositionFactorFlawed(uint256 id);
error LBPair__InsufficientLiquidityMinted(uint256 id);
error LBPair__InsufficientLiquidityBurned(uint256 id);
error LBPair__WrongLengths();
error LBPair__OnlyStrictlyIncreasingId();
error LBPair__OnlyFactory();
error LBPair__DistributionsOverflow();
error LBPair__OnlyFeeRecipient(address feeRecipient, address sender);
error LBPair__OracleNotEnoughSample();
error LBPair__AlreadyInitialized();
error LBPair__OracleNewSizeTooSmall(uint256 newSize, uint256 oracleSize);
error LBPair__FlashLoanCallbackFailed();
error LBPair__FlashLoanInvalidBalance();
error LBPair__FlashLoanInvalidToken();
/** BinHelper errors */
error BinHelper__BinStepOverflows(uint256 bp);
error BinHelper__IdOverflows();
/** Math128x128 errors */
error Math128x128__PowerUnderflow(uint256 x, int256 y);
error Math128x128__LogUnderflow();
/** Math512Bits errors */
error Math512Bits__MulDivOverflow(uint256 prod1, uint256 denominator);
error Math512Bits__ShiftDivOverflow(uint256 prod1, uint256 denominator);
error Math512Bits__MulShiftOverflow(uint256 prod1, uint256 offset);
error Math512Bits__OffsetOverflows(uint256 offset);
/** Oracle errors */
error Oracle__AlreadyInitialized(uint256 _index);
error Oracle__LookUpTimestampTooOld(uint256 _minTimestamp, uint256 _lookUpTimestamp);
error Oracle__NotInitialized();
/** PendingOwnable errors */
error PendingOwnable__NotOwner();
error PendingOwnable__NotPendingOwner();
error PendingOwnable__PendingOwnerAlreadySet();
error PendingOwnable__NoPendingOwner();
error PendingOwnable__AddressZero();
/** ReentrancyGuardUpgradeable errors */
error ReentrancyGuardUpgradeable__ReentrantCall();
error ReentrancyGuardUpgradeable__AlreadyInitialized();
/** SafeCast errors */
error SafeCast__Exceeds256Bits(uint256 x);
error SafeCast__Exceeds248Bits(uint256 x);
error SafeCast__Exceeds240Bits(uint256 x);
error SafeCast__Exceeds232Bits(uint256 x);
error SafeCast__Exceeds224Bits(uint256 x);
error SafeCast__Exceeds216Bits(uint256 x);
error SafeCast__Exceeds208Bits(uint256 x);
error SafeCast__Exceeds200Bits(uint256 x);
error SafeCast__Exceeds192Bits(uint256 x);
error SafeCast__Exceeds184Bits(uint256 x);
error SafeCast__Exceeds176Bits(uint256 x);
error SafeCast__Exceeds168Bits(uint256 x);
error SafeCast__Exceeds160Bits(uint256 x);
error SafeCast__Exceeds152Bits(uint256 x);
error SafeCast__Exceeds144Bits(uint256 x);
error SafeCast__Exceeds136Bits(uint256 x);
error SafeCast__Exceeds128Bits(uint256 x);
error SafeCast__Exceeds120Bits(uint256 x);
error SafeCast__Exceeds112Bits(uint256 x);
error SafeCast__Exceeds104Bits(uint256 x);
error SafeCast__Exceeds96Bits(uint256 x);
error SafeCast__Exceeds88Bits(uint256 x);
error SafeCast__Exceeds80Bits(uint256 x);
error SafeCast__Exceeds72Bits(uint256 x);
error SafeCast__Exceeds64Bits(uint256 x);
error SafeCast__Exceeds56Bits(uint256 x);
error SafeCast__Exceeds48Bits(uint256 x);
error SafeCast__Exceeds40Bits(uint256 x);
error SafeCast__Exceeds32Bits(uint256 x);
error SafeCast__Exceeds24Bits(uint256 x);
error SafeCast__Exceeds16Bits(uint256 x);
error SafeCast__Exceeds8Bits(uint256 x);
/** TreeMath errors */
error TreeMath__ErrorDepthSearch();
/** JoeLibrary errors */
error JoeLibrary__IdenticalAddresses();
error JoeLibrary__AddressZero();
error JoeLibrary__InsufficientAmount();
error JoeLibrary__InsufficientLiquidity();
/** TokenHelper errors */
error TokenHelper__NonContract();
error TokenHelper__CallFailed();
error TokenHelper__TransferFailed();
/** LBQuoter errors */
error LBQuoter_InvalidLength();// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "openzeppelin/token/ERC20/IERC20.sol";
import "./ILBPair.sol";
import "./IPendingOwnable.sol";
/// @title Liquidity Book Factory Interface
/// @author Trader Joe
/// @notice Required interface of LBFactory contract
interface ILBFactory is IPendingOwnable {
/// @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 FeeParametersSet(
address indexed sender,
ILBPair indexed LBPair,
uint256 binStep,
uint256 baseFactor,
uint256 filterPeriod,
uint256 decayPeriod,
uint256 reductionFactor,
uint256 variableFeeControl,
uint256 protocolShare,
uint256 maxVolatilityAccumulated
);
event FactoryLockedStatusUpdated(bool unlocked);
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 maxVolatilityAccumulated,
uint256 sampleLifetime
);
event PresetRemoved(uint256 indexed binStep);
event QuoteAssetAdded(IERC20 indexed quoteAsset);
event QuoteAssetRemoved(IERC20 indexed quoteAsset);
function MAX_FEE() external pure returns (uint256);
function MIN_BIN_STEP() external pure returns (uint256);
function MAX_BIN_STEP() external pure returns (uint256);
function MAX_PROTOCOL_SHARE() external pure returns (uint256);
function LBPairImplementation() external view returns (address);
function getNumberOfQuoteAssets() external view returns (uint256);
function getQuoteAsset(uint256 index) external view returns (IERC20);
function isQuoteAsset(IERC20 token) external view returns (bool);
function feeRecipient() external view returns (address);
function flashLoanFee() external view returns (uint256);
function creationUnlocked() external view returns (bool);
function allLBPairs(uint256 id) external returns (ILBPair);
function getNumberOfLBPairs() external view returns (uint256);
function getLBPairInformation(
IERC20 tokenX,
IERC20 tokenY,
uint256 binStep
) external view returns (LBPairInformation memory);
function getPreset(uint16 binStep)
external
view
returns (
uint256 baseFactor,
uint256 filterPeriod,
uint256 decayPeriod,
uint256 reductionFactor,
uint256 variableFeeControl,
uint256 protocolShare,
uint256 maxAccumulator,
uint256 sampleLifetime
);
function getAllBinSteps() external view returns (uint256[] memory presetsBinStep);
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,
uint256 binStep,
bool ignored
) external;
function setPreset(
uint16 binStep,
uint16 baseFactor,
uint16 filterPeriod,
uint16 decayPeriod,
uint16 reductionFactor,
uint24 variableFeeControl,
uint16 protocolShare,
uint24 maxVolatilityAccumulated,
uint16 sampleLifetime
) 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 maxVolatilityAccumulated
) external;
function setFeeRecipient(address feeRecipient) external;
function setFlashLoanFee(uint256 flashLoanFee) external;
function setFactoryLockedState(bool locked) 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 "openzeppelin/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 token,
uint256 amount,
uint256 fee,
bytes calldata data
) external returns (bytes32);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "openzeppelin/token/ERC20/IERC20.sol";
import "../libraries/FeeHelper.sol";
import "./ILBFactory.sol";
import "./ILBFlashLoanCallback.sol";
/// @title Liquidity Book Pair Interface
/// @author Trader Joe
/// @notice Required interface of LBPair contract
interface ILBPair {
/// @dev Structure to store the reserves of bins:
/// - reserveX: The current reserve of tokenX of the bin
/// - reserveY: The current reserve of tokenY of the bin
struct Bin {
uint112 reserveX;
uint112 reserveY;
uint256 accTokenXPerShare;
uint256 accTokenYPerShare;
}
/// @dev Structure to store the information of the pair such as:
/// slot0:
/// - activeId: The current id used for swaps, this is also linked with the price
/// - reserveX: The sum of amounts of tokenX across all bins
/// slot1:
/// - reserveY: The sum of amounts of tokenY across all bins
/// - oracleSampleLifetime: The lifetime of an oracle sample
/// - oracleSize: The current size of the oracle, can be increase by users
/// - oracleActiveSize: The current active size of the oracle, composed only from non empty data sample
/// - oracleLastTimestamp: The current last timestamp at which a sample was added to the circular buffer
/// - oracleId: The current id of the oracle
/// slot2:
/// - feesX: The current amount of fees to distribute in tokenX (total, protocol)
/// slot3:
/// - feesY: The current amount of fees to distribute in tokenY (total, protocol)
struct PairInformation {
uint24 activeId;
uint136 reserveX;
uint136 reserveY;
uint16 oracleSampleLifetime;
uint16 oracleSize;
uint16 oracleActiveSize;
uint40 oracleLastTimestamp;
uint16 oracleId;
FeeHelper.FeesDistribution feesX;
FeeHelper.FeesDistribution feesY;
}
/// @dev Structure to store the debts of users
/// - debtX: The tokenX's debt
/// - debtY: The tokenY's debt
struct Debts {
uint256 debtX;
uint256 debtY;
}
/// @dev Structure to store fees:
/// - tokenX: The amount of fees of token X
/// - tokenY: The amount of fees of token Y
struct Fees {
uint128 tokenX;
uint128 tokenY;
}
/// @dev Structure to minting informations:
/// - amountXIn: The amount of token X sent
/// - amountYIn: The amount of token Y sent
/// - amountXAddedToPair: The amount of token X that have been actually added to the pair
/// - amountYAddedToPair: The amount of token Y that have been actually added to the pair
/// - activeFeeX: Fees X currently generated
/// - activeFeeY: Fees Y currently generated
/// - totalDistributionX: Total distribution of token X. Should be 1e18 (100%) or 0 (0%)
/// - totalDistributionY: Total distribution of token Y. Should be 1e18 (100%) or 0 (0%)
/// - id: Id of the current working bin when looping on the distribution array
/// - amountX: The amount of token X deposited in the current bin
/// - amountY: The amount of token Y deposited in the current bin
/// - distributionX: Distribution of token X for the current working bin
/// - distributionY: Distribution of token Y for the current working bin
struct MintInfo {
uint256 amountXIn;
uint256 amountYIn;
uint256 amountXAddedToPair;
uint256 amountYAddedToPair;
uint256 activeFeeX;
uint256 activeFeeY;
uint256 totalDistributionX;
uint256 totalDistributionY;
uint256 id;
uint256 amountX;
uint256 amountY;
uint256 distributionX;
uint256 distributionY;
}
event Swap(
address indexed sender,
address indexed recipient,
uint256 indexed id,
bool swapForY,
uint256 amountIn,
uint256 amountOut,
uint256 volatilityAccumulated,
uint256 fees
);
event FlashLoan(
address indexed sender,
ILBFlashLoanCallback indexed receiver,
IERC20 token,
uint256 amount,
uint256 fee
);
event CompositionFee(
address indexed sender,
address indexed recipient,
uint256 indexed id,
uint256 feesX,
uint256 feesY
);
event DepositedToBin(
address indexed sender,
address indexed recipient,
uint256 indexed id,
uint256 amountX,
uint256 amountY
);
event WithdrawnFromBin(
address indexed sender,
address indexed recipient,
uint256 indexed id,
uint256 amountX,
uint256 amountY
);
event FeesCollected(address indexed sender, address indexed recipient, uint256 amountX, uint256 amountY);
event ProtocolFeesCollected(address indexed sender, address indexed recipient, uint256 amountX, uint256 amountY);
event OracleSizeIncreased(uint256 previousSize, uint256 newSize);
function tokenX() external view returns (IERC20);
function tokenY() external view returns (IERC20);
function factory() external view returns (ILBFactory);
function getReservesAndId()
external
view
returns (
uint256 reserveX,
uint256 reserveY,
uint256 activeId
);
function getGlobalFees()
external
view
returns (
uint128 feesXTotal,
uint128 feesYTotal,
uint128 feesXProtocol,
uint128 feesYProtocol
);
function getOracleParameters()
external
view
returns (
uint256 oracleSampleLifetime,
uint256 oracleSize,
uint256 oracleActiveSize,
uint256 oracleLastTimestamp,
uint256 oracleId,
uint256 min,
uint256 max
);
function getOracleSampleFrom(uint256 timeDelta)
external
view
returns (
uint256 cumulativeId,
uint256 cumulativeAccumulator,
uint256 cumulativeBinCrossed
);
function feeParameters() external view returns (FeeHelper.FeeParameters memory);
function findFirstNonEmptyBinId(uint24 id_, bool sentTokenY) external view returns (uint24 id);
function getBin(uint24 id) external view returns (uint256 reserveX, uint256 reserveY);
function pendingFees(address account, uint256[] memory ids)
external
view
returns (uint256 amountX, uint256 amountY);
function swap(bool sentTokenY, address to) external returns (uint256 amountXOut, uint256 amountYOut);
function flashLoan(
ILBFlashLoanCallback receiver,
IERC20 token,
uint256 amount,
bytes calldata data
) external;
function mint(
uint256[] calldata ids,
uint256[] calldata distributionX,
uint256[] calldata distributionY,
address to
)
external
returns (
uint256 amountXAddedToPair,
uint256 amountYAddedToPair,
uint256[] memory liquidityMinted
);
function burn(
uint256[] calldata ids,
uint256[] calldata amounts,
address to
) external returns (uint256 amountX, uint256 amountY);
function increaseOracleLength(uint16 newSize) external;
function collectFees(address account, uint256[] calldata ids) external returns (uint256 amountX, uint256 amountY);
function collectProtocolFees() external returns (uint128 amountX, uint128 amountY);
function setFeesParameters(bytes32 packedFeeParameters) external;
function forceDecay() external;
function initialize(
IERC20 tokenX,
IERC20 tokenY,
uint24 activeId,
uint16 sampleLifetime,
bytes32 packedFeeParameters
) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
/// @title Liquidity Book Pending Ownable Interface
/// @author Trader Joe
/// @notice Required interface of Pending Ownable contract used for LBFactory
interface IPendingOwnable {
event PendingOwnerSet(address indexed pendingOwner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function owner() external view returns (address);
function pendingOwner() external view returns (address);
function setPendingOwner(address pendingOwner) external;
function revokePendingOwner() external;
function becomeOwner() external;
function renounceOwnership() external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "../LBErrors.sol";
import "./Math128x128.sol";
/// @title Liquidity Book Bin Helper Library
/// @author Trader Joe
/// @notice Contract used to convert bin ID to price and back
library BinHelper {
using Math128x128 for uint256;
int256 private constant REAL_ID_SHIFT = 1 << 23;
/// @notice Returns the id corresponding to the given price
/// @dev The id may be inaccurate due to rounding issues, always trust getPriceFromId rather than
/// getIdFromPrice
/// @param _price The price of y per x as a 128.128-binary fixed-point number
/// @param _binStep The bin step
/// @return The id corresponding to this price
function getIdFromPrice(uint256 _price, uint256 _binStep) internal pure returns (uint24) {
unchecked {
uint256 _binStepValue = _getBPValue(_binStep);
// can't overflow as `2**23 + log2(price) < 2**23 + 2**128 < max(uint256)`
int256 _id = REAL_ID_SHIFT + _price.log2() / _binStepValue.log2();
if (_id < 0 || uint256(_id) > type(uint24).max) revert BinHelper__IdOverflows();
return uint24(uint256(_id));
}
}
/// @notice Returns the price corresponding to the given ID, as a 128.128-binary fixed-point number
/// @dev This is the trusted function to link id to price, the other way may be inaccurate
/// @param _id The id
/// @param _binStep The bin step
/// @return The price corresponding to this id, as a 128.128-binary fixed-point number
function getPriceFromId(uint256 _id, uint256 _binStep) internal pure returns (uint256) {
if (_id > uint256(type(uint24).max)) revert BinHelper__IdOverflows();
unchecked {
int256 _realId = int256(_id) - REAL_ID_SHIFT;
return _getBPValue(_binStep).power(_realId);
}
}
/// @notice Returns the (1 + bp) value as a 128.128-decimal fixed-point number
/// @param _binStep The bp value in [1; 100] (referring to 0.01% to 1%)
/// @return The (1+bp) value as a 128.128-decimal fixed-point number
function _getBPValue(uint256 _binStep) internal pure returns (uint256) {
if (_binStep == 0 || _binStep > Constants.BASIS_POINT_MAX) revert BinHelper__BinStepOverflows(_binStep);
unchecked {
// can't overflow as `max(result) = 2**128 + 10_000 << 128 / 10_000 < max(uint256)`
return Constants.SCALE + (_binStep << Constants.SCALE_OFFSET) / Constants.BASIS_POINT_MAX;
}
}
}// 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 {
/// @notice Returns the closest non-zero bit of `integer` to the right (of left) of the `bit` bits that is not `bit`
/// @param _integer The integer as a uint256
/// @param _bit The bit index
/// @param _rightSide Whether we're searching in the right side of the tree (true) or the left side (false)
/// @return The index of the closest non-zero bit. If there is no closest bit, it returns max(uint256)
function closestBit(
uint256 _integer,
uint8 _bit,
bool _rightSide
) internal pure returns (uint256) {
return _rightSide ? closestBitRight(_integer, _bit - 1) : closestBitLeft(_integer, _bit + 1);
}
/// @notice Returns the most (or least) significant bit of `_integer`
/// @param _integer The integer
/// @param _isMostSignificant Whether we want the most (true) or the least (false) significant bit
/// @return The index of the most (or least) significant bit
function significantBit(uint256 _integer, bool _isMostSignificant) internal pure returns (uint8) {
return _isMostSignificant ? mostSignificantBit(_integer) : leastSignificantBit(_integer);
}
/// @notice 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;
}
}
/// @notice 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;
}
}
/// @notice Returns the index of the most significant bit of x
/// @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) {
unchecked {
if (x >= 1 << 128) {
x >>= 128;
msb = 128;
}
if (x >= 1 << 64) {
x >>= 64;
msb += 64;
}
if (x >= 1 << 32) {
x >>= 32;
msb += 32;
}
if (x >= 1 << 16) {
x >>= 16;
msb += 16;
}
if (x >= 1 << 8) {
x >>= 8;
msb += 8;
}
if (x >= 1 << 4) {
x >>= 4;
msb += 4;
}
if (x >= 1 << 2) {
x >>= 2;
msb += 2;
}
if (x >= 1 << 1) {
msb += 1;
}
}
}
/// @notice Returns the index of the least significant bit of x
/// @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) {
unchecked {
if (x << 128 != 0) {
x <<= 128;
lsb = 128;
}
if (x << 64 != 0) {
x <<= 64;
lsb += 64;
}
if (x << 32 != 0) {
x <<= 32;
lsb += 32;
}
if (x << 16 != 0) {
x <<= 16;
lsb += 16;
}
if (x << 8 != 0) {
x <<= 8;
lsb += 8;
}
if (x << 4 != 0) {
x <<= 4;
lsb += 4;
}
if (x << 2 != 0) {
x <<= 2;
lsb += 2;
}
if (x << 1 != 0) {
lsb += 1;
}
return 255 - lsb;
}
}
}// 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 {
uint256 internal constant SCALE_OFFSET = 128;
uint256 internal constant SCALE = 1 << SCALE_OFFSET;
uint256 internal constant PRECISION = 1e18;
uint256 internal constant BASIS_POINT_MAX = 10_000;
/// @dev The expected return after a successful flash loan
bytes32 internal constant CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
/// @title Liquidity Book Decoder Library
/// @author Trader Joe
/// @notice Helper contract used for decoding bytes32 sample
library Decoder {
/// @notice Internal function to decode a bytes32 sample using a mask and offset
/// @dev This function can overflow
/// @param _sample The sample as a bytes32
/// @param _mask The mask
/// @param _offset The offset
/// @return value The decoded value
function decode(
bytes32 _sample,
uint256 _mask,
uint256 _offset
) internal pure returns (uint256 value) {
assembly {
value := and(shr(_offset, _sample), _mask)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "./Constants.sol";
import "./SafeCast.sol";
import "./SafeMath.sol";
/// @title Liquidity Book Fee Helper Library
/// @author Trader Joe
/// @notice Helper contract used for fees calculation
library FeeHelper {
using SafeCast for uint256;
using SafeMath for uint256;
/// @dev Structure to store the protocol fees:
/// - binStep: The bin step
/// - baseFactor: The base factor
/// - filterPeriod: The filter period, where the fees stays constant
/// - decayPeriod: The decay period, where the fees are halved
/// - reductionFactor: The reduction factor, used to calculate the reduction of the accumulator
/// - variableFeeControl: The variable fee control, used to control the variable fee, can be 0 to disable them
/// - protocolShare: The share of fees sent to protocol
/// - maxVolatilityAccumulated: The max value of volatility accumulated
/// - volatilityAccumulated: The value of volatility accumulated
/// - volatilityReference: The value of volatility reference
/// - indexRef: The index reference
/// - time: The last time the accumulator was called
struct FeeParameters {
// 144 lowest bits in slot
uint16 binStep;
uint16 baseFactor;
uint16 filterPeriod;
uint16 decayPeriod;
uint16 reductionFactor;
uint24 variableFeeControl;
uint16 protocolShare;
uint24 maxVolatilityAccumulated;
// 112 highest bits in slot
uint24 volatilityAccumulated;
uint24 volatilityReference;
uint24 indexRef;
uint40 time;
}
/// @dev Structure used during swaps to distributes the fees:
/// - total: The total amount of fees
/// - protocol: The amount of fees reserved for protocol
struct FeesDistribution {
uint128 total;
uint128 protocol;
}
/// @notice Update the value of the volatility accumulated
/// @param _fp The current fee parameters
/// @param _activeId The current active id
function updateVariableFeeParameters(FeeParameters memory _fp, uint256 _activeId) internal view {
uint256 _deltaT = block.timestamp - _fp.time;
if (_deltaT >= _fp.filterPeriod || _fp.time == 0) {
_fp.indexRef = uint24(_activeId);
if (_deltaT < _fp.decayPeriod) {
unchecked {
// This can't overflow as `reductionFactor <= BASIS_POINT_MAX`
_fp.volatilityReference = uint24(
(uint256(_fp.reductionFactor) * _fp.volatilityAccumulated) / Constants.BASIS_POINT_MAX
);
}
} else {
_fp.volatilityReference = 0;
}
}
_fp.time = (block.timestamp).safe40();
updateVolatilityAccumulated(_fp, _activeId);
}
/// @notice Update the volatility accumulated
/// @param _fp The fee parameter
/// @param _activeId The current active id
function updateVolatilityAccumulated(FeeParameters memory _fp, uint256 _activeId) internal pure {
uint256 volatilityAccumulated = (_activeId.absSub(_fp.indexRef) * Constants.BASIS_POINT_MAX) +
_fp.volatilityReference;
_fp.volatilityAccumulated = volatilityAccumulated > _fp.maxVolatilityAccumulated
? _fp.maxVolatilityAccumulated
: uint24(volatilityAccumulated);
}
/// @notice Returns the base fee added to a swap, with 18 decimals
/// @param _fp The current fee parameters
/// @return The fee with 18 decimals precision
function getBaseFee(FeeParameters memory _fp) internal pure returns (uint256) {
unchecked {
return uint256(_fp.baseFactor) * _fp.binStep * 1e10;
}
}
/// @notice Returns the variable fee added to a swap, with 18 decimals
/// @param _fp The current fee parameters
/// @return variableFee The variable fee with 18 decimals precision
function getVariableFee(FeeParameters memory _fp) internal pure returns (uint256 variableFee) {
if (_fp.variableFeeControl != 0) {
// Can't overflow as the max value is `max(uint24) * (max(uint24) * max(uint16)) ** 2 < max(uint104)`
// It returns 18 decimals as:
// decimals(variableFeeControl * (volatilityAccumulated * binStep)**2 / 100) = 4 + (4 + 4) * 2 - 2 = 18
unchecked {
uint256 _prod = uint256(_fp.volatilityAccumulated) * _fp.binStep;
variableFee = (_prod * _prod * _fp.variableFeeControl + 99) / 100;
}
}
}
/// @notice Return the amount of fees from an amount
/// @dev Rounds amount up, follows `amount = amountWithFees - getFeeAmountFrom(fp, amountWithFees)`
/// @param _fp The current fee parameter
/// @param _amountWithFees The amount of token sent
/// @return The fee amount from the amount sent
function getFeeAmountFrom(FeeParameters memory _fp, uint256 _amountWithFees) internal pure returns (uint256) {
return (_amountWithFees * getTotalFee(_fp) + Constants.PRECISION - 1) / (Constants.PRECISION);
}
/// @notice Return the fees to add to an amount
/// @dev Rounds amount up, follows `amountWithFees = amount + getFeeAmount(fp, amount)`
/// @param _fp The current fee parameter
/// @param _amount The amount of token sent
/// @return The fee amount to add to the amount
function getFeeAmount(FeeParameters memory _fp, uint256 _amount) internal pure returns (uint256) {
uint256 _fee = getTotalFee(_fp);
uint256 _denominator = Constants.PRECISION - _fee;
return (_amount * _fee + _denominator - 1) / _denominator;
}
/// @notice Return the fees added when an user adds liquidity and change the ratio in the active bin
/// @dev Rounds amount up
/// @param _fp The current fee parameter
/// @param _amountWithFees The amount of token sent
/// @return The fee amount
function getFeeAmountForC(FeeParameters memory _fp, uint256 _amountWithFees) internal pure returns (uint256) {
uint256 _fee = getTotalFee(_fp);
uint256 _denominator = Constants.PRECISION * Constants.PRECISION;
return (_amountWithFees * _fee * (_fee + Constants.PRECISION) + _denominator - 1) / _denominator;
}
/// @notice Return the fees distribution added to an amount
/// @param _fp The current fee parameter
/// @param _fees The fee amount
/// @return fees The fee distribution
function getFeeAmountDistribution(FeeParameters memory _fp, uint256 _fees)
internal
pure
returns (FeesDistribution memory fees)
{
fees.total = _fees.safe128();
// unsafe math is fine because total >= protocol
unchecked {
fees.protocol = uint128((_fees * _fp.protocolShare) / Constants.BASIS_POINT_MAX);
}
}
/// @notice Return the total fee, i.e. baseFee + variableFee
/// @param _fp The current fee parameter
/// @return The total fee, with 18 decimals
function getTotalFee(FeeParameters memory _fp) private pure returns (uint256) {
unchecked {
return getBaseFee(_fp) + getVariableFee(_fp);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "../LBErrors.sol";
import "./BitMath.sol";
import "./Constants.sol";
import "./Math512Bits.sol";
/// @title Liquidity Book Math Helper Library
/// @author Trader Joe
/// @notice Helper contract used for power and log calculations
library Math128x128 {
using Math512Bits for uint256;
using BitMath for uint256;
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 Math128x128__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^20; 2^20[
/// @return result The result of `x^y`
function power(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 pow := x
if gt(x, 0xffffffffffffffffffffffffffffffff) {
pow := div(not(0), pow)
invert := iszero(invert)
}
if and(absY, 0x1) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x2) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x4) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x8) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x10) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x20) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x40) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x80) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x100) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x200) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x400) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x800) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x1000) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x2000) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x4000) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x8000) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x10000) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x20000) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x40000) {
result := shr(128, mul(result, pow))
}
pow := shr(128, mul(pow, pow))
if and(absY, 0x80000) {
result := shr(128, mul(result, pow))
}
}
}
// revert if y is too big or if x^y underflowed
if (result == 0) revert Math128x128__PowerUnderflow(x, y);
return invert ? type(uint256).max / result : result;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "../LBErrors.sol";
import "./BitMath.sol";
/// @title Liquidity Book Math Helper Library
/// @author Trader Joe
/// @notice Helper contract used for full precision calculations
library Math512Bits {
using BitMath for uint256;
/// @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 x * y >> 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,
uint256 offset
) internal pure returns (uint256 result) {
if (offset > 255) revert Math512Bits__OffsetOverflows(offset);
(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 Math512Bits__MulShiftOverflow(prod1, offset);
unchecked {
result += prod1 << (256 - offset);
}
}
}
/// @notice Calculates x * y >> offset 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 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,
uint256 offset
) internal pure returns (uint256 result) {
unchecked {
result = mulShiftRoundDown(x, y, offset);
if (mulmod(x, y, 1 << offset) != 0) result += 1;
}
}
/// @notice Calculates 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,
uint256 offset,
uint256 denominator
) internal pure returns (uint256 result) {
if (offset > 255) revert Math512Bits__OffsetOverflows(offset);
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 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,
uint256 offset,
uint256 denominator
) internal pure returns (uint256 result) {
result = shiftDivRoundDown(x, offset, denominator);
unchecked {
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 Math512Bits__MulDivOverflow(prod1, denominator);
// 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;
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "../LBErrors.sol";
import "../interfaces/IPendingOwnable.sol";
/// @title Pending Ownable
/// @author Trader Joe
/// @notice 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 ownership of this contract is transferred using the
/// push and pull pattern, the current owner set a `pendingOwner` using
/// {setPendingOwner} and that address can then call {becomeOwner} to become the
/// owner of that contract. The main logic and comments comes from OpenZeppelin's
/// Ownable contract.
///
/// By default, the owner account will be the one that deploys the contract. This
/// can later be changed with {setPendingOwner} and {becomeOwner}.
///
/// 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
contract PendingOwnable is IPendingOwnable {
address private _owner;
address private _pendingOwner;
/// @notice Throws if called by any account other than the owner.
modifier onlyOwner() {
if (msg.sender != _owner) revert PendingOwnable__NotOwner();
_;
}
/// @notice Throws if called by any account other than the pending owner.
modifier onlyPendingOwner() {
if (msg.sender != _pendingOwner || msg.sender == address(0)) revert PendingOwnable__NotPendingOwner();
_;
}
/// @notice Initializes the contract setting the deployer as the initial owner
constructor() {
_transferOwnership(msg.sender);
}
/// @notice Returns the address of the current owner
/// @return The address of the current owner
function owner() public view override returns (address) {
return _owner;
}
/// @notice Returns the address of the current pending owner
/// @return The address of the current pending owner
function pendingOwner() public view override returns (address) {
return _pendingOwner;
}
/// @notice Sets the pending owner address. This address will be able to become
/// the owner of this contract by calling {becomeOwner}
function setPendingOwner(address pendingOwner_) public override onlyOwner {
if (pendingOwner_ == address(0)) revert PendingOwnable__AddressZero();
if (_pendingOwner != address(0)) revert PendingOwnable__PendingOwnerAlreadySet();
_setPendingOwner(pendingOwner_);
}
/// @notice Revoke the pending owner address. This address will not be able to
/// call {becomeOwner} to become the owner anymore.
/// Can only be called by the owner
function revokePendingOwner() public override onlyOwner {
if (_pendingOwner == address(0)) revert PendingOwnable__NoPendingOwner();
_setPendingOwner(address(0));
}
/// @notice Transfers the ownership to the new owner (`pendingOwner).
/// Can only be called by the pending owner
function becomeOwner() public override onlyPendingOwner {
_transferOwnership(msg.sender);
}
/// @notice Leaves the contract without owner. It will not be possible to call
/// `onlyOwner` functions anymore. Can only be called by the current owner.
///
/// NOTE: Renouncing ownership will leave the contract without an owner,
/// thereby removing any functionality that is only available to the owner.
function renounceOwnership() public override onlyOwner {
_transferOwnership(address(0));
}
/// @notice Transfers ownership of the contract to a new account (`newOwner`).
/// Internal function without access restriction.
/// @param _newOwner The address of the new owner
function _transferOwnership(address _newOwner) internal virtual {
address _oldOwner = _owner;
_owner = _newOwner;
_pendingOwner = address(0);
emit OwnershipTransferred(_oldOwner, _newOwner);
}
/// @notice Push the new owner, it needs to be pulled to be effective.
/// Internal function without access restriction.
/// @param pendingOwner_ The address of the new pending owner
function _setPendingOwner(address pendingOwner_) internal virtual {
_pendingOwner = pendingOwner_;
emit PendingOwnerSet(pendingOwner_);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
import "../LBErrors.sol";
/// @title Liquidity Book Safe Cast Library
/// @author Trader Joe
/// @notice Helper contract used for converting uint values safely
library SafeCast {
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
/// @notice 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(x);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
/// @title Liquidity Book Safe Math Helper Library
/// @author Trader Joe
/// @notice Helper contract used for calculating absolute value safely
library SafeMath {
/// @notice absSub, can't underflow or overflow
/// @param x The first value
/// @param y The second value
/// @return The result of abs(x - y)
function absSub(uint256 x, uint256 y) internal pure returns (uint256) {
unchecked {
return x > y ? x - y : y - x;
}
}
}{
"remappings": [
"ds-test/=lib/forge-std/lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/openzeppelin-contracts/contracts/"
],
"optimizer": {
"enabled": true,
"runs": 800
},
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_feeRecipient","type":"address"},{"internalType":"uint256","name":"_flashLoanFee","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"bp","type":"uint256"}],"name":"BinHelper__BinStepOverflows","type":"error"},{"inputs":[],"name":"BinHelper__IdOverflows","type":"error"},{"inputs":[],"name":"LBFactory__AddressZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"binStep","type":"uint256"}],"name":"LBFactory__BinStepHasNoPreset","type":"error"},{"inputs":[{"internalType":"uint256","name":"lowerBound","type":"uint256"},{"internalType":"uint16","name":"binStep","type":"uint16"},{"internalType":"uint256","name":"higherBound","type":"uint256"}],"name":"LBFactory__BinStepRequirementsBreached","type":"error"},{"inputs":[{"internalType":"uint16","name":"filterPeriod","type":"uint16"},{"internalType":"uint16","name":"decayPeriod","type":"uint16"}],"name":"LBFactory__DecreasingPeriods","type":"error"},{"inputs":[],"name":"LBFactory__FactoryLockIsAlreadyInTheSameState","type":"error"},{"inputs":[{"internalType":"uint256","name":"fees","type":"uint256"},{"internalType":"uint256","name":"maxFees","type":"uint256"}],"name":"LBFactory__FeesAboveMax","type":"error"},{"inputs":[{"internalType":"uint256","name":"fees","type":"uint256"},{"internalType":"uint256","name":"maxFees","type":"uint256"}],"name":"LBFactory__FlashLoanFeeAboveMax","type":"error"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"LBFactory__FunctionIsLockedForUsers","type":"error"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"LBFactory__IdenticalAddresses","type":"error"},{"inputs":[],"name":"LBFactory__ImplementationNotSet","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":[],"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":"uint16","name":"protocolShare","type":"uint16"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"LBFactory__ProtocolShareOverflows","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":"uint16","name":"reductionFactor","type":"uint16"},{"internalType":"uint256","name":"max","type":"uint256"}],"name":"LBFactory__ReductionFactorOverflows","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":"LBPairImplementation","type":"address"}],"name":"LBFactory__SameImplementation","type":"error"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"int256","name":"y","type":"int256"}],"name":"Math128x128__PowerUnderflow","type":"error"},{"inputs":[],"name":"PendingOwnable__AddressZero","type":"error"},{"inputs":[],"name":"PendingOwnable__NoPendingOwner","type":"error"},{"inputs":[],"name":"PendingOwnable__NotOwner","type":"error"},{"inputs":[],"name":"PendingOwnable__NotPendingOwner","type":"error"},{"inputs":[],"name":"PendingOwnable__PendingOwnerAlreadySet","type":"error"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"SafeCast__Exceeds16Bits","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"unlocked","type":"bool"}],"name":"FactoryLockedStatusUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"contract ILBPair","name":"LBPair","type":"address"},{"indexed":false,"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":"maxVolatilityAccumulated","type":"uint256"}],"name":"FeeParametersSet","type":"event"},{"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":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"PendingOwnerSet","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":"maxVolatilityAccumulated","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sampleLifetime","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"},{"inputs":[],"name":"LBPairImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BIN_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PROTOCOL_SHARE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BIN_STEP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_quoteAsset","type":"address"}],"name":"addQuoteAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allLBPairs","outputs":[{"internalType":"contract ILBPair","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"becomeOwner","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":"_LBPair","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"creationUnlocked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeRecipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"flashLoanFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract ILBPair","name":"_LBPair","type":"address"}],"name":"forceDecay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllBinSteps","outputs":[{"internalType":"uint256[]","name":"presetsBinStep","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":[{"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":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumberOfLBPairs","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumberOfQuoteAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"_binStep","type":"uint16"}],"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":"maxVolatilityAccumulated","type":"uint256"},{"internalType":"uint256","name":"sampleLifetime","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"getQuoteAsset","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"}],"name":"isQuoteAsset","outputs":[{"internalType":"bool","name":"","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":"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":[],"name":"revokePendingOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"_locked","type":"bool"}],"name":"setFactoryLockedState","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":"_maxVolatilityAccumulated","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":"uint256","name":"_binStep","type":"uint256"},{"internalType":"bool","name":"_ignored","type":"bool"}],"name":"setLBPairIgnored","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_LBPairImplementation","type":"address"}],"name":"setLBPairImplementation","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner_","type":"address"}],"name":"setPendingOwner","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":"_maxVolatilityAccumulated","type":"uint24"},{"internalType":"uint16","name":"_sampleLifetime","type":"uint16"}],"name":"setPreset","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b5060405162002c9038038062002c908339810160408190526200003491620001f0565b6200003f33620000d1565b67016345785d8a00008111156200007f57604051635e8988c160e01b81526004810182905267016345785d8a000060248201526044015b60405180910390fd5b6200008a826200012b565b60048190556040805160008152602081018390527f5c34e91c94c78b662a45d0bd4a25a4e32c584c54a45a76e4a4d43be27ba40e50910160405180910390a150506200022c565b600080546001600160a01b038381166001600160a01b031980841682178555600180549091169055604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b0381166200015357604051632573cfb960e21b815260040160405180910390fd5b6003546001600160a01b039081169082168114156200019157604051634fcea97160e01b81526001600160a01b038316600482015260240162000076565b600380546001600160a01b0319166001600160a01b0384811691821790925560408051928416835260208301919091527f15d80a013f22151bc7246e3bc132e12828cde19de98870475e3fa70840152721910160405180910390a15050565b600080604083850312156200020457600080fd5b82516001600160a01b03811681146200021c57600080fd5b6020939093015192949293505050565b612a54806200023c6000396000f3fe608060405234801561001057600080fd5b50600436106102415760003560e01c8063704037bd11610145578063bc063e1a116100bd578063e30c39781161008c578063e92d0d5d11610071578063e92d0d5d146104dd578063f89a4cd5146104f0578063f9dca9891461050357600080fd5b8063e30c3978146104b9578063e74b981b146104ca57600080fd5b8063bc063e1a14610471578063c42069ec14610480578063ddbfd94114610493578063e203a31f146104a657600080fd5b806380c5061e11610114578063935ea51b116100f9578063935ea51b14610407578063a931208f14610455578063b03847811461045e57600080fd5b806380c5061e146103ee5780638da5cb5b146103f657600080fd5b8063704037bd146103ab578063715018a6146103cb57806372e47b8c146103d35780637df880e3146103e657600080fd5b80634847cdc8116101d85780635b35875c116101a7578063659ac74b1161018c578063659ac74b146103705780636622e0d71461038357806367ab8a4e146103a357600080fd5b80635b35875c146103475780635c779d6d1461035c57600080fd5b80634847cdc8146103105780634e937c3a14610319578063509ceb90146103215780635a4409231461033457600080fd5b806322f3fe141161021457806322f3fe141461029c57806327721842146102af5780633c78a941146102d257806346904840146102e557600080fd5b8063093ff769146102465780630af97c9a1461025b57806310e9ec4a1461026e578063200aa7e314610289575b600080fd5b610259610254366004612524565b61050b565b005b6102596102693660046125e2565b610693565b610276606481565b6040519081526020015b60405180910390f35b61025961029736600461269a565b6107da565b6102596102aa3660046126eb565b61097e565b6102c26102bd366004612706565b610a4c565b6040519015158152602001610280565b6102596102e0366004612706565b610a5f565b6003546102f8906001600160a01b031681565b6040516001600160a01b039091168152602001610280565b61027660045481565b600554610276565b6002546102f8906001600160a01b031681565b610259610342366004612706565b610ae0565b61034f610b75565b6040516102809190612723565b6003546102c290600160a01b900460ff1681565b6102f861037e366004612767565b610c28565b6103966103913660046127b4565b61122e565b60405161028091906127ed565b6102596113fd565b6103be6103b9366004612861565b61145d565b60405161028091906128a2565b610259611494565b6102f86103e13660046128de565b6114c9565b610276600181565b6102766114f3565b6000546001600160a01b03166102f8565b61041a6104153660046128f7565b611504565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c083015260e082015261010001610280565b6102766109c481565b61025961046c366004612706565b611604565b61027667016345785d8a000081565b61025961048e366004612706565b611769565b6102596104a1366004612706565b6117f1565b6102596104b43660046128f7565b611886565b6001546001600160a01b03166102f8565b6102596104d8366004612706565b611957565b6102596104eb3660046128de565b61198b565b6102f86104fe3660046128de565b611a52565b610259611a5f565b6000546001600160a01b0316331461053657604051639f216c1360e01b815260040160405180910390fd5b60006105478b8b8b61ffff16611a9e565b6020015190506001600160a01b0381166105965760405163b65ee95360e01b81526001600160a01b03808d1660048301528b16602482015261ffff8a1660448201526064015b60405180910390fd5b60006105a88a8a8a8a8a8a8a8a611b48565b6040516354b5fc8760e01b8152600481018290529091506001600160a01b038316906354b5fc8790602401600060405180830381600087803b1580156105ed57600080fd5b505af1158015610601573d6000803e3d6000fd5b50506040805161ffff8e811682528d811660208301528c8116828401528b811660608301528a8116608083015262ffffff8a811660a084015290891660c0830152871660e082015290516001600160a01b03861693503392507f63a7af39b7b68b9c3f2dfe93e5f32d9faecb4c6c98733bb608f757e62f816c0d918190036101000190a3505050505050505050505050565b6000546001600160a01b031633146106be57604051639f216c1360e01b815260040160405180910390fd5b60006106d08a8a8a8a8a8a8a8a611b48565b61ffff8b16600081815260086020526040902060f085901b7fffff0000000000000000000000000000000000000000000000000000000000001671ffffffffffffffffffffffffffffffffffff84161790819055600754929350919081901c60011661075557600161ffff8d161b1761074d81600160f81b612928565b600781905590505b6040805161ffff8d811682528c811660208301528b8116828401528a8116606083015262ffffff8a8116608084015289821660a0840152881660c083015286811660e08301529151918e16917f2f6cfdcc0e02e7355350f527dd3b5a957787b96f231165e48a3fdf90332a40cb918190036101000190a2505050505050505050505050565b6000546001600160a01b0316331461080557604051639f216c1360e01b815260040160405180910390fd5b6000806108128686611dbc565b6001600160a01b038083166000908152600660209081526040808320848616845282528083208a84528252918290208251608081018452905461ffff8116825262010000810490941691810182905260ff600160b01b85048116151593820193909352600160b81b90930490911615156060830152929450909250906108ab57604051632573cfb960e21b815260040160405180910390fd5b8315158160600151151514156108d357604051626ee66560e11b815260040160405180910390fd5b6001600160a01b038084166000908152600660209081526040808320868516845282528083208984528252918290208054881515600160b81b027fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff90911617905583015190519116907f44cf35361c9ff3c8c1397ec6410d5495cc481feaef35c9af11da1a637107de4f9061096d90871515815260200190565b60405180910390a250505050505050565b6000546001600160a01b031633146109a957604051639f216c1360e01b815260040160405180910390fd5b60035460ff600160a01b909104161515811515146109da576040516302dbbca560e21b815260040160405180910390fd5b60038054600160a01b8315027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091161790556040517fcdee7bf87b7a743b4cbe1d2d534c5248621b76f58460337e7fda92d5d23f412490610a4190831515815260200190565b60405180910390a150565b6000610a59600983611de5565b92915050565b6000546001600160a01b03163314610a8a57604051639f216c1360e01b815260040160405180910390fd5b806001600160a01b031663d3b9fbe46040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ac557600080fd5b505af1158015610ad9573d6000803e3d6000fd5b5050505050565b6000546001600160a01b03163314610b0b57604051639f216c1360e01b815260040160405180910390fd5b610b16600982611e0a565b610b3e576040516303ce0ad960e01b81526001600160a01b038216600482015260240161058d565b6040516001600160a01b038216907f84cc2115995684dcb0cd3d3a9565e3d32f075de81db70c8dc3a719b2a47af67e90600090a250565b60075460609060f881901c8015610c23578067ffffffffffffffff811115610b9f57610b9f612940565b604051908082528060200260200182016040528015610bc8578160200160208202803683370190505b509250600060015b60648111610c205783811c60011660011415610c185780858381518110610bf957610bf9612956565b60200260200101818152505082826001019250821415610c1857610c20565b600101610bd0565b50505b505090565b600080610c3d6000546001600160a01b031690565b600354909150600160a01b900460ff16158015610c635750336001600160a01b03821614155b15610c8257604051627487d360e71b815233600482015260240161058d565b6002546001600160a01b031680610cac576040516328b4fcf960e21b815260040160405180910390fd5b610cb7600987611de5565b610cdf57604051638e888ef360e01b81526001600160a01b038716600482015260240161058d565b856001600160a01b0316876001600160a01b03161415610d1d57604051632f9b185360e01b81526001600160a01b038816600482015260240161058d565b610d308562ffffff168561ffff16611e1f565b50600080610d3e8989611dbc565b90925090506001600160a01b038216610d6a57604051632573cfb960e21b815260040160405180910390fd5b6001600160a01b0382811660009081526006602090815260408083208585168452825280832061ffff8b1684529091529020546201000090041615610ddf5760405163cb27a43560e01b81526001600160a01b03808b1660048301528916602482015261ffff8716604482015260640161058d565b61ffff861660009081526008602052604090205480610e1757604051637d9160bf60e11b815261ffff8816600482015260240161058d565b604080516001600160a01b038581166020808401919091529085168284015261ffff8a16606080840191909152835180840390910181526080909201909252805191012071ffffffffffffffffffffffffffffffffffff82169160f01c90610e7f8682611e5f565b60405163d32db43760e01b81526001600160a01b038e811660048301528d8116602483015262ffffff8d16604483015261ffff85166064830152608482018690529199509089169063d32db4379060a401600060405180830381600087803b158015610eea57600080fd5b505af1158015610efe573d6000803e3d6000fd5b5050505060405180608001604052808a61ffff168152602001896001600160a01b03168152602001886001600160a01b0316336001600160a01b031614151581526020016000151581525060066000876001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008b61ffff16815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160000160166101000a81548160ff02191690831515021790555060608201518160000160176101000a81548160ff0219169083151502179055509050506005889080600181540180825580915050600190039060005260206000200160009091909190916101000a8154816001600160a01b0302191690836001600160a01b031602179055506000600b6000876001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000205490508961ffff166001901b8160001c1760001b90508060001c600160f81b6110f59190612928565b6001600160a01b038088166000908152600b602090815260408083208a8516845290915290209190915560055461ffff8c1692508d8216918f16907f2c8d104b27c6b7f4492017a6f5cf3803043688934ebcaa6a03540beeaf976aff908c906111609060019061296c565b604080516001600160a01b03909316835260208301919091520160405180910390a46040805161ffff808c168252601086901c811660208381019190915286901c811682840152603086901c8116606083015285831c8116608083015262ffffff605087901c811660a0840152606887901c90911660c0830152607886901c1660e082015290516001600160a01b038a169133917f63a7af39b7b68b9c3f2dfe93e5f32d9faecb4c6c98733bb608f757e62f816c0d918190036101000190a350505050505050949350505050565b606060008061123d8585611dbc565b6001600160a01b038281166000908152600b6020908152604080832093851683529290522054919350915060f881901c80156113f3578067ffffffffffffffff81111561128c5761128c612940565b6040519080825280602002602001820160405280156112de57816020015b6040805160808101825260008082526020808301829052928201819052606082015282526000199092019101816112aa5790505b509450600060015b606481116113f05783811c600116600114156113e8576001600160a01b03808716600090815260066020908152604080832089851684528252808320858452825291829020825160808082018552915461ffff811682526201000081049095169281019290925260ff600160b01b85048116151583850152600160b81b909404909316151560608201528151928301909152908061138384611f16565b61ffff16815260200182602001516001600160a01b03168152602001826040015115158152602001826060015115158152508884815181106113c7576113c7612956565b6020026020010181905250838360010193508314156113e657506113f0565b505b6001016112e6565b50505b5050505092915050565b6000546001600160a01b0316331461142857604051639f216c1360e01b815260040160405180910390fd5b6001546001600160a01b03166114515760405163ecfad6bf60e01b815260040160405180910390fd5b61145b6000611f43565b565b60408051608081018252600080825260208201819052918101829052606081019190915261148c848484611a9e565b949350505050565b6000546001600160a01b031633146114bf57604051639f216c1360e01b815260040160405180910390fd5b61145b6000611f8d565b600581815481106114d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60006114ff6009611fe7565b905090565b61ffff811660009081526008602052604081205481908190819081908190819081908061154a57604051637d9160bf60e11b815261ffff8b16600482015260240161058d565b600061ffff82168b61ffff161461156057600080fd5b61157a61ffff611571601084612928565b925083831c1690565b995061158d61ffff611571601084612928565b98506115a061ffff611571601084612928565b97506115b361ffff611571601084612928565b96506115c762ffffff611571601084612928565b95506115da61ffff611571601884612928565b94506115ee62ffffff611571601084612928565b935060f082901c92505050919395975091939597565b6000546001600160a01b0316331461162f57604051639f216c1360e01b815260040160405180910390fd5b306001600160a01b0316816001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015611677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169b9190612983565b6001600160a01b0316146116cd57604051630a3e70af60e11b81526001600160a01b038216600482015260240161058d565b6002546001600160a01b0390811690821681141561170957604051630ded3b9560e31b81526001600160a01b038316600482015260240161058d565b600280546001600160a01b0319166001600160a01b0384811691821790925560408051928416835260208301919091527f900d0e3d359f50e4f923ecdc06b401e07dbb9f485e17b07bcfc91a13000b277e91015b60405180910390a15050565b6000546001600160a01b0316331461179457604051639f216c1360e01b815260040160405180910390fd5b6001600160a01b0381166117bb576040516391f3851560e01b815260040160405180910390fd5b6001546001600160a01b0316156117e55760405163716b1fbf60e01b815260040160405180910390fd5b6117ee81611f43565b50565b6000546001600160a01b0316331461181c57604051639f216c1360e01b815260040160405180910390fd5b611827600982611ff1565b61184f57604051638e888ef360e01b81526001600160a01b038216600482015260240161058d565b6040516001600160a01b038216907f0b767739217755d8af5a2ba75b181a19fa1750f8bb701f09311cb19a90140cb390600090a250565b6000546001600160a01b031633146118b157604051639f216c1360e01b815260040160405180910390fd5b61ffff81166000908152600860205260409020546118e857604051637d9160bf60e11b815261ffff8216600482015260240161058d565b6007546118fe600161ffff84161b60001961296c565b1661190d600160f81b8261296c565b600781905561ffff83166000818152600860205260408082208290555192935090917fdd86b848bb56ff540caa68683fa467d0e7eb5f8b2d44e4ee435742eeeae9be139190a25050565b6000546001600160a01b0316331461198257604051639f216c1360e01b815260040160405180910390fd5b6117ee81612006565b6000546001600160a01b031633146119b657604051639f216c1360e01b815260040160405180910390fd5b600454818114156119dd57604051631baa31e960e21b81526004810183905260240161058d565b67016345785d8a0000821115611a1757604051635e8988c160e01b81526004810183905267016345785d8a0000602482015260440161058d565b600482905560408051828152602081018490527f5c34e91c94c78b662a45d0bd4a25a4e32c584c54a45a76e4a4d43be27ba40e50910161175d565b6000610a596009836120c1565b6001546001600160a01b031633141580611a77575033155b15611a9557604051633982680960e11b815260040160405180910390fd5b61145b33611f8d565b604080516080810182526000808252602082018190529181018290526060810191909152611acc8484611dbc565b6001600160a01b03918216600090815260066020908152604080832093851683529281528282209582529485528190208151608081018352905461ffff811682526201000081049093169481019490945260ff600160b01b83048116151591850191909152600160b81b90910416151560608301525092915050565b600060018961ffff161080611b61575060648961ffff16115b15611b9357604051634f95635f60e11b81526001600482015261ffff8a1660248201526064604482018190520161058d565b8561ffff168761ffff1610611bc95760405163744d432160e11b815261ffff80891660048301528716602482015260440161058d565b6127108561ffff161115611bfe5760405163632afa6960e11b815261ffff86166004820152612710602482015260440161058d565b6109c48361ffff161115611c3357604051630d0ada2960e41b815261ffff841660048201526109c4602482015260440161058d565b6000611c4661ffff808c16908b166129a0565b611c55906402540be4006129a0565b90506000611c6c61ffff8c1662ffffff86166129a0565b90506000606462ffffff8816611c8284806129a0565b611c8c91906129a0565b611c9691906129bf565b905067016345785d8a0000611cab8285612928565b1115611ce657611cbb8184612928565b604051633fb210a760e21b8152600481019190915267016345785d8a0000602482015260440161058d565b50506040805171ffffff000000000000000000000000000000607886901b1660208201527fffff00000000000000000000000000000000000000000000000000000000000060f087811b821660318401527fffffff000000000000000000000000000000000000000000000000000000000060e88a901b16603384015289811b821660368401528a811b821660388401528b811b8216603a8401528c811b8216603c8401528d901b16603e820152019050604051602081830303815290604052611daf906129e1565b9998505050505050505050565b600080826001600160a01b0316846001600160a01b03161115611ddd579192915b509192909150565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b6000611e03836001600160a01b0384166120cd565b600062ffffff831115611e455760405163163d8bab60e21b815260040160405180910390fd5b627fffff19830161148c81611e598561211c565b90612162565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528360601b60148201527f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006028820152826037826000f59150506001600160a01b038116610a595760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c6564000000000000000000604482015260640161058d565b8061ffff81168114611f3e5760405163506fbff560e01b81526004810183905260240161058d565b919050565b600180546001600160a01b0319166001600160a01b0383169081179091556040517f68f49b346b94582a8b5f9d10e3fe3365318fe8f191ff8dce7c59c6cad06b02f590600090a250565b600080546001600160a01b038381166001600160a01b031980841682178555600180549091169055604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000610a59825490565b6000611e03836001600160a01b0384166123cd565b6001600160a01b03811661202d57604051632573cfb960e21b815260040160405180910390fd5b6003546001600160a01b0390811690821681141561206957604051634fcea97160e01b81526001600160a01b038316600482015260240161058d565b600380546001600160a01b0319166001600160a01b0384811691821790925560408051928416835260208301919091527f15d80a013f22151bc7246e3bc132e12828cde19de98870475e3fa70840152721910161175d565b6000611e0383836124c0565b600081815260018301602052604081205461211457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610a59565b506000610a59565b600081158061212c575061271082115b1561214d576040516374da1e1160e11b81526004810183905260240161058d565b612710608083901b04600160801b0192915050565b600080808361217a5750600160801b9150610a599050565b5082600081121561218c579015906000035b6210000081101561238557600160801b9250846fffffffffffffffffffffffffffffffff8111156121bf57911591600019045b60018216156121d05792830260801c925b800260801c60028216156121e65792830260801c925b800260801c60048216156121fc5792830260801c925b800260801c60088216156122125792830260801c925b800260801c60108216156122285792830260801c925b800260801c602082161561223e5792830260801c925b800260801c60408216156122545792830260801c925b8002608090811c9082161561226b5792830260801c925b800260801c6101008216156122825792830260801c925b800260801c6102008216156122995792830260801c925b800260801c6104008216156122b05792830260801c925b800260801c6108008216156122c75792830260801c925b800260801c6110008216156122de5792830260801c925b800260801c6120008216156122f55792830260801c925b800260801c61400082161561230c5792830260801c925b800260801c6180008216156123235792830260801c925b800260801c6201000082161561233b5792830260801c925b800260801c620200008216156123535792830260801c925b800260801c6204000082161561236b5792830260801c925b800260801c620800008216156123835792830260801c925b505b826123ad57604051630e9c7d6160e31b8152600481018690526024810185905260440161058d565b816123b857826123c4565b6123c4836000196129bf565b95945050505050565b600081815260018301602052604081205480156124b65760006123f160018361296c565b85549091506000906124059060019061296c565b905081811461246a57600086600001828154811061242557612425612956565b906000526020600020015490508087600001848154811061244857612448612956565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061247b5761247b612a08565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610a59565b6000915050610a59565b60008260000182815481106124d7576124d7612956565b9060005260206000200154905092915050565b6001600160a01b03811681146117ee57600080fd5b803561ffff81168114611f3e57600080fd5b803562ffffff81168114611f3e57600080fd5b6000806000806000806000806000806101408b8d03121561254457600080fd5b8a3561254f816124ea565b995060208b013561255f816124ea565b985061256d60408c016124ff565b975061257b60608c016124ff565b965061258960808c016124ff565b955061259760a08c016124ff565b94506125a560c08c016124ff565b93506125b360e08c01612511565b92506125c26101008c016124ff565b91506125d16101208c01612511565b90509295989b9194979a5092959850565b60008060008060008060008060006101208a8c03121561260157600080fd5b61260a8a6124ff565b985061261860208b016124ff565b975061262660408b016124ff565b965061263460608b016124ff565b955061264260808b016124ff565b945061265060a08b01612511565b935061265e60c08b016124ff565b925061266c60e08b01612511565b915061267b6101008b016124ff565b90509295985092959850929598565b80358015158114611f3e57600080fd5b600080600080608085870312156126b057600080fd5b84356126bb816124ea565b935060208501356126cb816124ea565b9250604085013591506126e06060860161268a565b905092959194509250565b6000602082840312156126fd57600080fd5b611e038261268a565b60006020828403121561271857600080fd5b8135611e03816124ea565b6020808252825182820181905260009190848201906040850190845b8181101561275b5783518352928401929184019160010161273f565b50909695505050505050565b6000806000806080858703121561277d57600080fd5b8435612788816124ea565b93506020850135612798816124ea565b92506127a660408601612511565b91506126e0606086016124ff565b600080604083850312156127c757600080fd5b82356127d2816124ea565b915060208301356127e2816124ea565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561275b5761284e83855161ffff81511682526001600160a01b0360208201511660208301526040810151151560408301526060810151151560608301525050565b9284019260809290920191600101612809565b60008060006060848603121561287657600080fd5b8335612881816124ea565b92506020840135612891816124ea565b929592945050506040919091013590565b815161ffff1681526020808301516001600160a01b03169082015260408083015115159082015260608083015115159082015260808101610a59565b6000602082840312156128f057600080fd5b5035919050565b60006020828403121561290957600080fd5b611e03826124ff565b634e487b7160e01b600052601160045260246000fd5b6000821982111561293b5761293b612912565b500190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60008282101561297e5761297e612912565b500390565b60006020828403121561299557600080fd5b8151611e03816124ea565b60008160001904831182151516156129ba576129ba612912565b500290565b6000826129dc57634e487b7160e01b600052601260045260246000fd5b500490565b80516020808301519190811015612a02576000198160200360031b1b821691505b50919050565b634e487b7160e01b600052603160045260246000fdfea26469706673582212203b9f852cba9b69a7ead4adbbe5d3e43b7890dce2e48797cee6fa9fbfe22e2e6f64736f6c634300080a00330000000000000000000000001119fbb02f38764cd90f2d9fb35fedcd8378ac2a0000000000000000000000000000000000000000000000000000048c27395000
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102415760003560e01c8063704037bd11610145578063bc063e1a116100bd578063e30c39781161008c578063e92d0d5d11610071578063e92d0d5d146104dd578063f89a4cd5146104f0578063f9dca9891461050357600080fd5b8063e30c3978146104b9578063e74b981b146104ca57600080fd5b8063bc063e1a14610471578063c42069ec14610480578063ddbfd94114610493578063e203a31f146104a657600080fd5b806380c5061e11610114578063935ea51b116100f9578063935ea51b14610407578063a931208f14610455578063b03847811461045e57600080fd5b806380c5061e146103ee5780638da5cb5b146103f657600080fd5b8063704037bd146103ab578063715018a6146103cb57806372e47b8c146103d35780637df880e3146103e657600080fd5b80634847cdc8116101d85780635b35875c116101a7578063659ac74b1161018c578063659ac74b146103705780636622e0d71461038357806367ab8a4e146103a357600080fd5b80635b35875c146103475780635c779d6d1461035c57600080fd5b80634847cdc8146103105780634e937c3a14610319578063509ceb90146103215780635a4409231461033457600080fd5b806322f3fe141161021457806322f3fe141461029c57806327721842146102af5780633c78a941146102d257806346904840146102e557600080fd5b8063093ff769146102465780630af97c9a1461025b57806310e9ec4a1461026e578063200aa7e314610289575b600080fd5b610259610254366004612524565b61050b565b005b6102596102693660046125e2565b610693565b610276606481565b6040519081526020015b60405180910390f35b61025961029736600461269a565b6107da565b6102596102aa3660046126eb565b61097e565b6102c26102bd366004612706565b610a4c565b6040519015158152602001610280565b6102596102e0366004612706565b610a5f565b6003546102f8906001600160a01b031681565b6040516001600160a01b039091168152602001610280565b61027660045481565b600554610276565b6002546102f8906001600160a01b031681565b610259610342366004612706565b610ae0565b61034f610b75565b6040516102809190612723565b6003546102c290600160a01b900460ff1681565b6102f861037e366004612767565b610c28565b6103966103913660046127b4565b61122e565b60405161028091906127ed565b6102596113fd565b6103be6103b9366004612861565b61145d565b60405161028091906128a2565b610259611494565b6102f86103e13660046128de565b6114c9565b610276600181565b6102766114f3565b6000546001600160a01b03166102f8565b61041a6104153660046128f7565b611504565b604080519889526020890197909752958701949094526060860192909252608085015260a084015260c083015260e082015261010001610280565b6102766109c481565b61025961046c366004612706565b611604565b61027667016345785d8a000081565b61025961048e366004612706565b611769565b6102596104a1366004612706565b6117f1565b6102596104b43660046128f7565b611886565b6001546001600160a01b03166102f8565b6102596104d8366004612706565b611957565b6102596104eb3660046128de565b61198b565b6102f86104fe3660046128de565b611a52565b610259611a5f565b6000546001600160a01b0316331461053657604051639f216c1360e01b815260040160405180910390fd5b60006105478b8b8b61ffff16611a9e565b6020015190506001600160a01b0381166105965760405163b65ee95360e01b81526001600160a01b03808d1660048301528b16602482015261ffff8a1660448201526064015b60405180910390fd5b60006105a88a8a8a8a8a8a8a8a611b48565b6040516354b5fc8760e01b8152600481018290529091506001600160a01b038316906354b5fc8790602401600060405180830381600087803b1580156105ed57600080fd5b505af1158015610601573d6000803e3d6000fd5b50506040805161ffff8e811682528d811660208301528c8116828401528b811660608301528a8116608083015262ffffff8a811660a084015290891660c0830152871660e082015290516001600160a01b03861693503392507f63a7af39b7b68b9c3f2dfe93e5f32d9faecb4c6c98733bb608f757e62f816c0d918190036101000190a3505050505050505050505050565b6000546001600160a01b031633146106be57604051639f216c1360e01b815260040160405180910390fd5b60006106d08a8a8a8a8a8a8a8a611b48565b61ffff8b16600081815260086020526040902060f085901b7fffff0000000000000000000000000000000000000000000000000000000000001671ffffffffffffffffffffffffffffffffffff84161790819055600754929350919081901c60011661075557600161ffff8d161b1761074d81600160f81b612928565b600781905590505b6040805161ffff8d811682528c811660208301528b8116828401528a8116606083015262ffffff8a8116608084015289821660a0840152881660c083015286811660e08301529151918e16917f2f6cfdcc0e02e7355350f527dd3b5a957787b96f231165e48a3fdf90332a40cb918190036101000190a2505050505050505050505050565b6000546001600160a01b0316331461080557604051639f216c1360e01b815260040160405180910390fd5b6000806108128686611dbc565b6001600160a01b038083166000908152600660209081526040808320848616845282528083208a84528252918290208251608081018452905461ffff8116825262010000810490941691810182905260ff600160b01b85048116151593820193909352600160b81b90930490911615156060830152929450909250906108ab57604051632573cfb960e21b815260040160405180910390fd5b8315158160600151151514156108d357604051626ee66560e11b815260040160405180910390fd5b6001600160a01b038084166000908152600660209081526040808320868516845282528083208984528252918290208054881515600160b81b027fffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffff90911617905583015190519116907f44cf35361c9ff3c8c1397ec6410d5495cc481feaef35c9af11da1a637107de4f9061096d90871515815260200190565b60405180910390a250505050505050565b6000546001600160a01b031633146109a957604051639f216c1360e01b815260040160405180910390fd5b60035460ff600160a01b909104161515811515146109da576040516302dbbca560e21b815260040160405180910390fd5b60038054600160a01b8315027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff9091161790556040517fcdee7bf87b7a743b4cbe1d2d534c5248621b76f58460337e7fda92d5d23f412490610a4190831515815260200190565b60405180910390a150565b6000610a59600983611de5565b92915050565b6000546001600160a01b03163314610a8a57604051639f216c1360e01b815260040160405180910390fd5b806001600160a01b031663d3b9fbe46040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ac557600080fd5b505af1158015610ad9573d6000803e3d6000fd5b5050505050565b6000546001600160a01b03163314610b0b57604051639f216c1360e01b815260040160405180910390fd5b610b16600982611e0a565b610b3e576040516303ce0ad960e01b81526001600160a01b038216600482015260240161058d565b6040516001600160a01b038216907f84cc2115995684dcb0cd3d3a9565e3d32f075de81db70c8dc3a719b2a47af67e90600090a250565b60075460609060f881901c8015610c23578067ffffffffffffffff811115610b9f57610b9f612940565b604051908082528060200260200182016040528015610bc8578160200160208202803683370190505b509250600060015b60648111610c205783811c60011660011415610c185780858381518110610bf957610bf9612956565b60200260200101818152505082826001019250821415610c1857610c20565b600101610bd0565b50505b505090565b600080610c3d6000546001600160a01b031690565b600354909150600160a01b900460ff16158015610c635750336001600160a01b03821614155b15610c8257604051627487d360e71b815233600482015260240161058d565b6002546001600160a01b031680610cac576040516328b4fcf960e21b815260040160405180910390fd5b610cb7600987611de5565b610cdf57604051638e888ef360e01b81526001600160a01b038716600482015260240161058d565b856001600160a01b0316876001600160a01b03161415610d1d57604051632f9b185360e01b81526001600160a01b038816600482015260240161058d565b610d308562ffffff168561ffff16611e1f565b50600080610d3e8989611dbc565b90925090506001600160a01b038216610d6a57604051632573cfb960e21b815260040160405180910390fd5b6001600160a01b0382811660009081526006602090815260408083208585168452825280832061ffff8b1684529091529020546201000090041615610ddf5760405163cb27a43560e01b81526001600160a01b03808b1660048301528916602482015261ffff8716604482015260640161058d565b61ffff861660009081526008602052604090205480610e1757604051637d9160bf60e11b815261ffff8816600482015260240161058d565b604080516001600160a01b038581166020808401919091529085168284015261ffff8a16606080840191909152835180840390910181526080909201909252805191012071ffffffffffffffffffffffffffffffffffff82169160f01c90610e7f8682611e5f565b60405163d32db43760e01b81526001600160a01b038e811660048301528d8116602483015262ffffff8d16604483015261ffff85166064830152608482018690529199509089169063d32db4379060a401600060405180830381600087803b158015610eea57600080fd5b505af1158015610efe573d6000803e3d6000fd5b5050505060405180608001604052808a61ffff168152602001896001600160a01b03168152602001886001600160a01b0316336001600160a01b031614151581526020016000151581525060066000876001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b0316815260200190815260200160002060008b61ffff16815260200190815260200160002060008201518160000160006101000a81548161ffff021916908361ffff16021790555060208201518160000160026101000a8154816001600160a01b0302191690836001600160a01b0316021790555060408201518160000160166101000a81548160ff02191690831515021790555060608201518160000160176101000a81548160ff0219169083151502179055509050506005889080600181540180825580915050600190039060005260206000200160009091909190916101000a8154816001600160a01b0302191690836001600160a01b031602179055506000600b6000876001600160a01b03166001600160a01b031681526020019081526020016000206000866001600160a01b03166001600160a01b031681526020019081526020016000205490508961ffff166001901b8160001c1760001b90508060001c600160f81b6110f59190612928565b6001600160a01b038088166000908152600b602090815260408083208a8516845290915290209190915560055461ffff8c1692508d8216918f16907f2c8d104b27c6b7f4492017a6f5cf3803043688934ebcaa6a03540beeaf976aff908c906111609060019061296c565b604080516001600160a01b03909316835260208301919091520160405180910390a46040805161ffff808c168252601086901c811660208381019190915286901c811682840152603086901c8116606083015285831c8116608083015262ffffff605087901c811660a0840152606887901c90911660c0830152607886901c1660e082015290516001600160a01b038a169133917f63a7af39b7b68b9c3f2dfe93e5f32d9faecb4c6c98733bb608f757e62f816c0d918190036101000190a350505050505050949350505050565b606060008061123d8585611dbc565b6001600160a01b038281166000908152600b6020908152604080832093851683529290522054919350915060f881901c80156113f3578067ffffffffffffffff81111561128c5761128c612940565b6040519080825280602002602001820160405280156112de57816020015b6040805160808101825260008082526020808301829052928201819052606082015282526000199092019101816112aa5790505b509450600060015b606481116113f05783811c600116600114156113e8576001600160a01b03808716600090815260066020908152604080832089851684528252808320858452825291829020825160808082018552915461ffff811682526201000081049095169281019290925260ff600160b01b85048116151583850152600160b81b909404909316151560608201528151928301909152908061138384611f16565b61ffff16815260200182602001516001600160a01b03168152602001826040015115158152602001826060015115158152508884815181106113c7576113c7612956565b6020026020010181905250838360010193508314156113e657506113f0565b505b6001016112e6565b50505b5050505092915050565b6000546001600160a01b0316331461142857604051639f216c1360e01b815260040160405180910390fd5b6001546001600160a01b03166114515760405163ecfad6bf60e01b815260040160405180910390fd5b61145b6000611f43565b565b60408051608081018252600080825260208201819052918101829052606081019190915261148c848484611a9e565b949350505050565b6000546001600160a01b031633146114bf57604051639f216c1360e01b815260040160405180910390fd5b61145b6000611f8d565b600581815481106114d957600080fd5b6000918252602090912001546001600160a01b0316905081565b60006114ff6009611fe7565b905090565b61ffff811660009081526008602052604081205481908190819081908190819081908061154a57604051637d9160bf60e11b815261ffff8b16600482015260240161058d565b600061ffff82168b61ffff161461156057600080fd5b61157a61ffff611571601084612928565b925083831c1690565b995061158d61ffff611571601084612928565b98506115a061ffff611571601084612928565b97506115b361ffff611571601084612928565b96506115c762ffffff611571601084612928565b95506115da61ffff611571601884612928565b94506115ee62ffffff611571601084612928565b935060f082901c92505050919395975091939597565b6000546001600160a01b0316331461162f57604051639f216c1360e01b815260040160405180910390fd5b306001600160a01b0316816001600160a01b031663c45a01556040518163ffffffff1660e01b8152600401602060405180830381865afa158015611677573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169b9190612983565b6001600160a01b0316146116cd57604051630a3e70af60e11b81526001600160a01b038216600482015260240161058d565b6002546001600160a01b0390811690821681141561170957604051630ded3b9560e31b81526001600160a01b038316600482015260240161058d565b600280546001600160a01b0319166001600160a01b0384811691821790925560408051928416835260208301919091527f900d0e3d359f50e4f923ecdc06b401e07dbb9f485e17b07bcfc91a13000b277e91015b60405180910390a15050565b6000546001600160a01b0316331461179457604051639f216c1360e01b815260040160405180910390fd5b6001600160a01b0381166117bb576040516391f3851560e01b815260040160405180910390fd5b6001546001600160a01b0316156117e55760405163716b1fbf60e01b815260040160405180910390fd5b6117ee81611f43565b50565b6000546001600160a01b0316331461181c57604051639f216c1360e01b815260040160405180910390fd5b611827600982611ff1565b61184f57604051638e888ef360e01b81526001600160a01b038216600482015260240161058d565b6040516001600160a01b038216907f0b767739217755d8af5a2ba75b181a19fa1750f8bb701f09311cb19a90140cb390600090a250565b6000546001600160a01b031633146118b157604051639f216c1360e01b815260040160405180910390fd5b61ffff81166000908152600860205260409020546118e857604051637d9160bf60e11b815261ffff8216600482015260240161058d565b6007546118fe600161ffff84161b60001961296c565b1661190d600160f81b8261296c565b600781905561ffff83166000818152600860205260408082208290555192935090917fdd86b848bb56ff540caa68683fa467d0e7eb5f8b2d44e4ee435742eeeae9be139190a25050565b6000546001600160a01b0316331461198257604051639f216c1360e01b815260040160405180910390fd5b6117ee81612006565b6000546001600160a01b031633146119b657604051639f216c1360e01b815260040160405180910390fd5b600454818114156119dd57604051631baa31e960e21b81526004810183905260240161058d565b67016345785d8a0000821115611a1757604051635e8988c160e01b81526004810183905267016345785d8a0000602482015260440161058d565b600482905560408051828152602081018490527f5c34e91c94c78b662a45d0bd4a25a4e32c584c54a45a76e4a4d43be27ba40e50910161175d565b6000610a596009836120c1565b6001546001600160a01b031633141580611a77575033155b15611a9557604051633982680960e11b815260040160405180910390fd5b61145b33611f8d565b604080516080810182526000808252602082018190529181018290526060810191909152611acc8484611dbc565b6001600160a01b03918216600090815260066020908152604080832093851683529281528282209582529485528190208151608081018352905461ffff811682526201000081049093169481019490945260ff600160b01b83048116151591850191909152600160b81b90910416151560608301525092915050565b600060018961ffff161080611b61575060648961ffff16115b15611b9357604051634f95635f60e11b81526001600482015261ffff8a1660248201526064604482018190520161058d565b8561ffff168761ffff1610611bc95760405163744d432160e11b815261ffff80891660048301528716602482015260440161058d565b6127108561ffff161115611bfe5760405163632afa6960e11b815261ffff86166004820152612710602482015260440161058d565b6109c48361ffff161115611c3357604051630d0ada2960e41b815261ffff841660048201526109c4602482015260440161058d565b6000611c4661ffff808c16908b166129a0565b611c55906402540be4006129a0565b90506000611c6c61ffff8c1662ffffff86166129a0565b90506000606462ffffff8816611c8284806129a0565b611c8c91906129a0565b611c9691906129bf565b905067016345785d8a0000611cab8285612928565b1115611ce657611cbb8184612928565b604051633fb210a760e21b8152600481019190915267016345785d8a0000602482015260440161058d565b50506040805171ffffff000000000000000000000000000000607886901b1660208201527fffff00000000000000000000000000000000000000000000000000000000000060f087811b821660318401527fffffff000000000000000000000000000000000000000000000000000000000060e88a901b16603384015289811b821660368401528a811b821660388401528b811b8216603a8401528c811b8216603c8401528d901b16603e820152019050604051602081830303815290604052611daf906129e1565b9998505050505050505050565b600080826001600160a01b0316846001600160a01b03161115611ddd579192915b509192909150565b6001600160a01b038116600090815260018301602052604081205415155b9392505050565b6000611e03836001600160a01b0384166120cd565b600062ffffff831115611e455760405163163d8bab60e21b815260040160405180910390fd5b627fffff19830161148c81611e598561211c565b90612162565b60006040517f3d602d80600a3d3981f3363d3d373d3d3d363d7300000000000000000000000081528360601b60148201527f5af43d82803e903d91602b57fd5bf300000000000000000000000000000000006028820152826037826000f59150506001600160a01b038116610a595760405162461bcd60e51b815260206004820152601760248201527f455243313136373a2063726561746532206661696c6564000000000000000000604482015260640161058d565b8061ffff81168114611f3e5760405163506fbff560e01b81526004810183905260240161058d565b919050565b600180546001600160a01b0319166001600160a01b0383169081179091556040517f68f49b346b94582a8b5f9d10e3fe3365318fe8f191ff8dce7c59c6cad06b02f590600090a250565b600080546001600160a01b038381166001600160a01b031980841682178555600180549091169055604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000610a59825490565b6000611e03836001600160a01b0384166123cd565b6001600160a01b03811661202d57604051632573cfb960e21b815260040160405180910390fd5b6003546001600160a01b0390811690821681141561206957604051634fcea97160e01b81526001600160a01b038316600482015260240161058d565b600380546001600160a01b0319166001600160a01b0384811691821790925560408051928416835260208301919091527f15d80a013f22151bc7246e3bc132e12828cde19de98870475e3fa70840152721910161175d565b6000611e0383836124c0565b600081815260018301602052604081205461211457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610a59565b506000610a59565b600081158061212c575061271082115b1561214d576040516374da1e1160e11b81526004810183905260240161058d565b612710608083901b04600160801b0192915050565b600080808361217a5750600160801b9150610a599050565b5082600081121561218c579015906000035b6210000081101561238557600160801b9250846fffffffffffffffffffffffffffffffff8111156121bf57911591600019045b60018216156121d05792830260801c925b800260801c60028216156121e65792830260801c925b800260801c60048216156121fc5792830260801c925b800260801c60088216156122125792830260801c925b800260801c60108216156122285792830260801c925b800260801c602082161561223e5792830260801c925b800260801c60408216156122545792830260801c925b8002608090811c9082161561226b5792830260801c925b800260801c6101008216156122825792830260801c925b800260801c6102008216156122995792830260801c925b800260801c6104008216156122b05792830260801c925b800260801c6108008216156122c75792830260801c925b800260801c6110008216156122de5792830260801c925b800260801c6120008216156122f55792830260801c925b800260801c61400082161561230c5792830260801c925b800260801c6180008216156123235792830260801c925b800260801c6201000082161561233b5792830260801c925b800260801c620200008216156123535792830260801c925b800260801c6204000082161561236b5792830260801c925b800260801c620800008216156123835792830260801c925b505b826123ad57604051630e9c7d6160e31b8152600481018690526024810185905260440161058d565b816123b857826123c4565b6123c4836000196129bf565b95945050505050565b600081815260018301602052604081205480156124b65760006123f160018361296c565b85549091506000906124059060019061296c565b905081811461246a57600086600001828154811061242557612425612956565b906000526020600020015490508087600001848154811061244857612448612956565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061247b5761247b612a08565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610a59565b6000915050610a59565b60008260000182815481106124d7576124d7612956565b9060005260206000200154905092915050565b6001600160a01b03811681146117ee57600080fd5b803561ffff81168114611f3e57600080fd5b803562ffffff81168114611f3e57600080fd5b6000806000806000806000806000806101408b8d03121561254457600080fd5b8a3561254f816124ea565b995060208b013561255f816124ea565b985061256d60408c016124ff565b975061257b60608c016124ff565b965061258960808c016124ff565b955061259760a08c016124ff565b94506125a560c08c016124ff565b93506125b360e08c01612511565b92506125c26101008c016124ff565b91506125d16101208c01612511565b90509295989b9194979a5092959850565b60008060008060008060008060006101208a8c03121561260157600080fd5b61260a8a6124ff565b985061261860208b016124ff565b975061262660408b016124ff565b965061263460608b016124ff565b955061264260808b016124ff565b945061265060a08b01612511565b935061265e60c08b016124ff565b925061266c60e08b01612511565b915061267b6101008b016124ff565b90509295985092959850929598565b80358015158114611f3e57600080fd5b600080600080608085870312156126b057600080fd5b84356126bb816124ea565b935060208501356126cb816124ea565b9250604085013591506126e06060860161268a565b905092959194509250565b6000602082840312156126fd57600080fd5b611e038261268a565b60006020828403121561271857600080fd5b8135611e03816124ea565b6020808252825182820181905260009190848201906040850190845b8181101561275b5783518352928401929184019160010161273f565b50909695505050505050565b6000806000806080858703121561277d57600080fd5b8435612788816124ea565b93506020850135612798816124ea565b92506127a660408601612511565b91506126e0606086016124ff565b600080604083850312156127c757600080fd5b82356127d2816124ea565b915060208301356127e2816124ea565b809150509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561275b5761284e83855161ffff81511682526001600160a01b0360208201511660208301526040810151151560408301526060810151151560608301525050565b9284019260809290920191600101612809565b60008060006060848603121561287657600080fd5b8335612881816124ea565b92506020840135612891816124ea565b929592945050506040919091013590565b815161ffff1681526020808301516001600160a01b03169082015260408083015115159082015260608083015115159082015260808101610a59565b6000602082840312156128f057600080fd5b5035919050565b60006020828403121561290957600080fd5b611e03826124ff565b634e487b7160e01b600052601160045260246000fd5b6000821982111561293b5761293b612912565b500190565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b60008282101561297e5761297e612912565b500390565b60006020828403121561299557600080fd5b8151611e03816124ea565b60008160001904831182151516156129ba576129ba612912565b500290565b6000826129dc57634e487b7160e01b600052601260045260246000fd5b500490565b80516020808301519190811015612a02576000198160200360031b1b821691505b50919050565b634e487b7160e01b600052603160045260246000fdfea26469706673582212203b9f852cba9b69a7ead4adbbe5d3e43b7890dce2e48797cee6fa9fbfe22e2e6f64736f6c634300080a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001119fbb02f38764cd90f2d9fb35fedcd8378ac2a0000000000000000000000000000000000000000000000000000048c27395000
-----Decoded View---------------
Arg [0] : _feeRecipient (address): 0x1119fbb02F38764CD90F2d9fB35FeDcd8378ac2A
Arg [1] : _flashLoanFee (uint256): 5000000000000
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000001119fbb02f38764cd90f2d9fb35fedcd8378ac2a
Arg [1] : 0000000000000000000000000000000000000000000000000000048c27395000
Loading...
Loading
OVERVIEW
One-stop-shop decentralized trading on Avalanche.Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.