Latest 25 from a total of 3,421 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Flash Liquidate ... | 87790171 | 67 days ago | IN | 0 MNT | 0.07970446 | ||||
| Flash Liquidate ... | 87790040 | 67 days ago | IN | 0 MNT | 0.08146005 | ||||
| Flash Liquidate ... | 87789696 | 67 days ago | IN | 0 MNT | 0.10575025 | ||||
| Flash Liquidate ... | 87789635 | 67 days ago | IN | 0 MNT | 0.11100443 | ||||
| Flash Liquidate ... | 87781683 | 68 days ago | IN | 0 MNT | 0.07210342 | ||||
| Flash Liquidate ... | 87763654 | 68 days ago | IN | 0 MNT | 0.08681163 | ||||
| Flash Liquidate ... | 87655011 | 70 days ago | IN | 0 MNT | 0.15532943 | ||||
| Flash Liquidate ... | 87654107 | 70 days ago | IN | 0 MNT | 0.06585861 | ||||
| Flash Liquidate ... | 87648336 | 71 days ago | IN | 0 MNT | 0.11187462 | ||||
| Flash Liquidate ... | 87642716 | 71 days ago | IN | 0 MNT | 0.08072815 | ||||
| Flash Liquidate ... | 87641267 | 71 days ago | IN | 0 MNT | 0.06772374 | ||||
| Flash Liquidate ... | 87639521 | 71 days ago | IN | 0 MNT | 0.0638114 | ||||
| Flash Liquidate ... | 87601984 | 72 days ago | IN | 0 MNT | 0.08979866 | ||||
| Flash Liquidate ... | 87088316 | 84 days ago | IN | 0 MNT | 0.06939861 | ||||
| Flash Liquidate ... | 87083091 | 84 days ago | IN | 0 MNT | 0.06881033 | ||||
| Flash Liquidate ... | 87078290 | 84 days ago | IN | 0 MNT | 0.07717073 | ||||
| Flash Liquidate ... | 87061308 | 84 days ago | IN | 0 MNT | 0.08391855 | ||||
| Flash Liquidate ... | 87034438 | 85 days ago | IN | 0 MNT | 0.07750788 | ||||
| Flash Liquidate ... | 87026979 | 85 days ago | IN | 0 MNT | 0.11694906 | ||||
| Flash Liquidate ... | 86960067 | 87 days ago | IN | 0 MNT | 0.05530983 | ||||
| Flash Liquidate ... | 86283767 | 102 days ago | IN | 0 MNT | 0.0670463 | ||||
| Flash Liquidate ... | 86043427 | 108 days ago | IN | 0 MNT | 0.06481063 | ||||
| Flash Liquidate ... | 86026328 | 108 days ago | IN | 0 MNT | 0.05568634 | ||||
| Flash Liquidate ... | 86026328 | 108 days ago | IN | 0 MNT | 0.05738821 | ||||
| Flash Liquidate ... | 86012289 | 108 days ago | IN | 0 MNT | 0.0556235 |
Latest 25 internal transactions (View All)
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 87790171 | 67 days ago | 1.00673434 MNT | ||||
| 87790171 | 67 days ago | 1.00673434 MNT | ||||
| 87790040 | 67 days ago | 1.14355542 MNT | ||||
| 87790040 | 67 days ago | 1.14355542 MNT | ||||
| 87789696 | 67 days ago | 1.14964035 MNT | ||||
| 87789696 | 67 days ago | 1.14964035 MNT | ||||
| 87789635 | 67 days ago | 0.9287186 MNT | ||||
| 87781683 | 68 days ago | 1.02135156 MNT | ||||
| 87781683 | 68 days ago | 1.02135156 MNT | ||||
| 87763654 | 68 days ago | 1.04498982 MNT | ||||
| 87763654 | 68 days ago | 1.04498982 MNT | ||||
| 87655011 | 70 days ago | 1.3484078 MNT | ||||
| 87655011 | 70 days ago | 1.3484078 MNT | ||||
| 87654107 | 70 days ago | 0.07542556 MNT | ||||
| 87654107 | 70 days ago | 0.07542556 MNT | ||||
| 87648336 | 71 days ago | 3.17336934 MNT | ||||
| 87648336 | 71 days ago | 3.17336934 MNT | ||||
| 87642716 | 71 days ago | 0.00119901 MNT | ||||
| 87642716 | 71 days ago | 0.00119901 MNT | ||||
| 87641267 | 71 days ago | 1.04527581 MNT | ||||
| 87641267 | 71 days ago | 1.04527581 MNT | ||||
| 87639521 | 71 days ago | 1.02425088 MNT | ||||
| 87639521 | 71 days ago | 1.02425088 MNT | ||||
| 87601984 | 72 days ago | 1.11017652 MNT | ||||
| 87601984 | 72 days ago | 1.11017652 MNT |
Cross-Chain Transactions
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import '../../common/library/UncheckedIncrement.sol';
import {IInitCore} from '../../interfaces/core/IInitCore.sol';
import {IPosManager} from '../../interfaces/core/IPosManager.sol';
import {ILendingPool} from '../../interfaces/lending_pool/ILendingPool.sol';
import {TokenFactors, IConfig} from '../../interfaces/core/IConfig.sol';
import {ILiqIncentiveCalculator} from '../../interfaces/core/ILiqIncentiveCalculator.sol';
import {IInitOracle} from '../../interfaces/oracle/IInitOracle.sol';
import {IMulticall} from '../../interfaces/common/IMulticall.sol';
import {SwapOperation, ISwapDataRegistry} from '../../interfaces/helper/liquidation_helper/ISwapDataRegistry.sol';
import {IInitLens} from '../../interfaces/helper/IInitLens.sol';
import {IWNative} from '../../interfaces/common/IWNative.sol';
import {
IERC20LiquidationBot,
ICallbackReceiver
} from '../../interfaces/helper/liquidation_helper/IERC20LiquidationBot.sol';
import {IERC20} from '@openzeppelin-contracts/token/ERC20/IERC20.sol';
import {SafeERC20} from '@openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol';
import {ERC721Holder} from '@openzeppelin-contracts/token/ERC721/utils/ERC721Holder.sol';
import {Math} from '@openzeppelin-contracts/utils/math/Math.sol';
contract ERC20LiquidationBot is ERC721Holder, IERC20LiquidationBot {
using SafeERC20 for IERC20;
using Math for uint;
using UncheckedIncrement for uint;
// constants
uint private constant ONE_E18 = 1e18;
uint private constant MAX_UINT = type(uint).max;
uint private constant BPS = 10_000;
uint8 private constant MODE = 1;
// immutables
address private immutable CORE;
address private immutable POS_MANAGER;
uint private immutable PLACEHOLDER_ID;
address private immutable SWAP_DATA_REGISTRY;
address private immutable ORACLE;
address private immutable LENS;
address private immutable WNATIVE;
uint private immutable BUFFER_BPS;
constructor(
address _core,
address _posManager,
address _registry,
address _lens,
address _wNative,
uint _bufferBPS
) {
CORE = _core;
POS_MANAGER = _posManager;
SWAP_DATA_REGISTRY = _registry;
ORACLE = IInitCore(_core).oracle();
LENS = _lens;
WNATIVE = _wNative;
// note: using 1 as mode since it can borrow any token and we don't care about token's factor here
PLACEHOLDER_ID = IInitCore(_core).createPos(MODE, address(this));
require(_bufferBPS <= BPS, 'LiquidationBot: INVALID_BUFFER_BPS');
BUFFER_BPS = _bufferBPS;
}
/// @inheritdoc IERC20LiquidationBot
function flashLiquidate(
uint _posId,
address _poolToBorrow,
address _router,
address _poolToRepay,
address _router2,
address _poolOut,
uint _minAmtOut
) public {
// flash liquidate
_flashLiquidate(_posId, _poolToBorrow, _router, _poolToRepay, _router2, _poolOut);
address tokenOut = ILendingPool(_poolOut).underlyingToken();
uint balance = IERC20(tokenOut).balanceOf(address(this));
// slippage check
require(balance >= _minAmtOut, 'LiquidationBot: INSUFFICIENT_OUTPUT_AMOUNT');
// transfer remaining to owner
IERC20(tokenOut).safeTransfer(msg.sender, balance);
}
/// @inheritdoc IERC20LiquidationBot
function flashLiquidateReturnNative(
uint _posId,
address _poolToBorrow,
address _router,
address _poolToRepay,
address _router2,
address _poolOut,
address _router3,
uint _minAmtOut
) external {
// flash liquidate
_flashLiquidate(_posId, _poolToBorrow, _router, _poolToRepay, _router2, _poolOut);
address collToken = ILendingPool(_poolOut).underlyingToken();
bool success;
// swap to wNative if needed
if (collToken != WNATIVE) {
// swap to wNative
_ensureApprove(collToken, _router3);
// get swap data from registry
bytes memory swapData = ISwapDataRegistry(SWAP_DATA_REGISTRY).getCalldata(
address(this),
collToken,
WNATIVE,
SwapOperation.EXACT_IN,
_router3,
IERC20(collToken).balanceOf(address(this))
);
// swap
(success,) = _router3.call(swapData);
require(success, 'LiquidationBot: SWAP_FAILED');
}
// withdraw wNative to native
uint balance = IERC20(WNATIVE).balanceOf(address(this));
IWNative(WNATIVE).withdraw(balance);
balance = address(this).balance;
// slippage check
require(balance >= _minAmtOut, 'LiquidationBot: INSUFFICIENT_OUTPUT_AMOUNT');
// transfer to msg.sender
(success,) = payable(msg.sender).call{value: balance}('');
require(success, 'LiquidationBot: NATIVE_TRANSFER_FAILED');
}
/// @inheritdoc ICallbackReceiver
function coreCallback(address, bytes calldata _data) external payable override returns (bytes memory result) {
// NOTE: there are 2 cases for liquidation and flash borrow repayment
// for liquidate position poolIn == _poolToBorrow of flashLiquidate and poolOut == _poolToRepay of flashLiquidate
// for repay flash borrow poolIn == _poolOut of flashLiquidate and poolOut == _poolToBorrow of flashLiquidate
(address router, address poolIn, address poolOut, uint posId, uint repayShares) =
abi.decode(_data, (address, address, address, uint, uint));
uint balance;
// if posId == PLACEHOLDER_ID, it means flash borrow repayment
if (posId == PLACEHOLDER_ID) {
// burn pool for underlying token to swap to repay flash borrow
balance = IERC20(poolIn).balanceOf(address(this));
IERC20(poolIn).safeTransfer(poolIn, balance);
IInitCore(CORE).burnTo(poolIn, address(this));
}
address tokenIn = ILendingPool(poolIn).underlyingToken();
address tokenOut = ILendingPool(poolOut).underlyingToken();
balance = IERC20(tokenIn).balanceOf(address(this));
// check if tokenIn is tokenOut no need to swap
if (tokenIn == tokenOut) return abi.encode(balance);
// get repayAmt
{
uint debtShares = IPosManager(POS_MANAGER).getPosDebtShares(posId, poolOut);
repayShares = repayShares.min(debtShares);
}
uint repayAmt = ILendingPool(poolOut).debtShareToAmtStored(repayShares);
// get swap data
bytes memory swapData = ISwapDataRegistry(SWAP_DATA_REGISTRY).getCalldata(
address(this),
tokenIn,
tokenOut,
SwapOperation.EXACT_OUT,
router,
repayAmt - IERC20(tokenOut).balanceOf(address(this))
);
// ensure approve tokenIn for router
_ensureApprove(tokenIn, router);
// swap
(bool success,) = router.call(swapData);
require(success, 'LiquidationBot: SWAP_FAILED');
return abi.encode(IERC20(tokenOut).balanceOf(address(this)));
}
/// @inheritdoc IERC20LiquidationBot
function getMaxRepayAmt(uint _posId, address _poolToRepay, address _poolOut)
external
returns (address repayToken, uint maxRepayAmt)
{
(repayToken, maxRepayAmt,,) = _getMaxRepayShares(_posId, _poolToRepay, _poolOut);
}
/// @inheritdoc IERC20LiquidationBot
function getLiquidationInfo(uint _posId)
external
returns (address bestPoolToRepay, address bestPoolOut, uint maxRepayAmt)
{
// get all coll and borr pools
(address[] memory collPools,,,,) = IPosManager(POS_MANAGER).getPosCollInfo(_posId);
(address[] memory borrPools,) = IPosManager(POS_MANAGER).getPosBorrInfo(_posId);
// get best pool to repay and pool to liquidate from repay value with incentive
uint maxRepayValWithIncentive_e36;
for (uint i; i < collPools.length; i = i.uinc()) {
for (uint j; j < borrPools.length; j = j.uinc()) {
(address repayToken, uint repayAmt,, uint incentiveMultipler_e18) =
_getMaxRepayShares(_posId, borrPools[j], collPools[i]);
if (repayAmt == 0) continue;
uint repayVal_e36 = repayAmt * IInitOracle(ORACLE).getPrice_e36(repayToken);
uint repayValWithIncentive_e36 = repayVal_e36.mulDiv(incentiveMultipler_e18, ONE_E18);
if (repayValWithIncentive_e36 > maxRepayValWithIncentive_e36) {
maxRepayAmt = repayAmt;
bestPoolToRepay = borrPools[j];
bestPoolOut = collPools[i];
}
}
}
}
function _ensureApprove(address _token, address _spender) internal {
if (IERC20(_token).allowance(address(this), _spender) == 0) {
IERC20(_token).approve(_spender, MAX_UINT);
}
}
function _getMaxRepayShares(uint _posId, address _poolToRepay, address _poolOut)
internal
returns (address repayToken, uint repayAmt, uint repayShares, uint incentiveMultipler_e18)
{
address config = IInitCore(CORE).config();
incentiveMultipler_e18;
{
// prepare value for equation
// get current credit
uint collCredit_e36 = IInitCore(CORE).getCollateralCreditCurrent_e36(_posId);
uint borrCredit_e36 = IInitCore(CORE).getBorrowCreditCurrent_e36(_posId);
// if position is healthy, return 0
if (collCredit_e36 >= borrCredit_e36) return (repayToken, 0, 0, 0);
repayToken = ILendingPool(_poolToRepay).underlyingToken();
uint16 mode = IPosManager(POS_MANAGER).getPosMode(_posId);
// get incentiveMultipler_e18
{
address liqIncentiveCalculator = IInitCore(CORE).liqIncentiveCalculator();
incentiveMultipler_e18 = ILiqIncentiveCalculator(liqIncentiveCalculator).getLiqIncentiveMultiplier_e18(
mode,
collCredit_e36 * ONE_E18 / borrCredit_e36,
repayToken,
ILendingPool(_poolOut).underlyingToken()
);
}
require(incentiveMultipler_e18 != 0, 'LiquidationBot: POSITION_HEALTHY');
// get max health after liquidation with buffer to avoid rounding error
uint maxHealthAfterLiquidation_e18 = IConfig(config).getMaxHealthAfterLiq_e18(mode) * BUFFER_BPS / BPS;
// get token factors
TokenFactors memory tokenOutFactors = IConfig(config).getTokenFactors(mode, _poolOut);
TokenFactors memory repayTokenFactors = IConfig(config).getTokenFactors(mode, _poolToRepay);
// equation: https://hackmd.io/@UZkiPM-qQH6ZHGMsfk-KGQ/SJ06AAp56
// calculate repayAmt
// note: repayAmt needs to be divided by token price to get actual amt
{
uint numerator = (maxHealthAfterLiquidation_e18 * borrCredit_e36) - (collCredit_e36 * ONE_E18);
uint denominator = maxHealthAfterLiquidation_e18 * repayTokenFactors.borrFactor_e18;
denominator -= (tokenOutFactors.collFactor_e18 * incentiveMultipler_e18);
repayAmt = numerator.mulDiv(ONE_E18, denominator);
}
}
uint repayTokenPrice_e36;
uint collTokenPrice_e36;
// get prices
{
address[] memory tokens = new address[](2);
tokens[0] = repayToken;
tokens[1] = ILendingPool(_poolOut).underlyingToken();
uint[] memory prices_e36 = IInitOracle(ORACLE).getPrices_e36(tokens);
repayTokenPrice_e36 = prices_e36[0];
collTokenPrice_e36 = prices_e36[1];
}
// get repayShares
repayAmt = repayAmt / repayTokenPrice_e36;
repayShares = ILendingPool(_poolToRepay).debtAmtToShareStored(repayAmt);
// take min of repayShares and totalDebtShares
{
uint totalDebtShares = IPosManager(POS_MANAGER).getPosDebtShares(_posId, _poolToRepay);
repayShares = repayShares.min(totalDebtShares);
}
// calculate real repayAmt from repayShares
repayAmt = ILendingPool(_poolToRepay).debtShareToAmtStored(repayShares);
// calculate expectedAmtOut
uint repayAmtWithIncentive = repayAmt * incentiveMultipler_e18 / ONE_E18;
uint expectedAmtOut = repayAmtWithIncentive * repayTokenPrice_e36 / collTokenPrice_e36;
uint collAmt = IPosManager(POS_MANAGER).getCollAmt(_posId, _poolOut);
uint amtOut = ILendingPool(_poolOut).toAmt(collAmt);
// check if amtOut < expectedAmtOut
if (amtOut < expectedAmtOut) {
// calculate repayAmt with amtOut
uint repayValWithIncentive = amtOut * collTokenPrice_e36 / repayTokenPrice_e36;
repayAmt = repayValWithIncentive * ONE_E18 / incentiveMultipler_e18;
repayShares = ILendingPool(_poolToRepay).debtAmtToShareStored(repayAmt);
}
}
function _flashLiquidate(
uint _posId,
address _poolToBorrow,
address _router,
address _poolToRepay,
address _router2,
address _poolOut
) internal {
require(_posId != PLACEHOLDER_ID, 'LiquidationBot: INVALID_POS_ID');
// get max repayShares for _poolToRepay and _poolOut
(address repayToken,, uint repayShares,) = _getMaxRepayShares(_posId, _poolToRepay, _poolOut);
bytes[] memory multicallData = new bytes[](5);
// approve repayToken for liquidation
_ensureApprove(repayToken, CORE);
{
uint borrAmt = ILendingPool(_poolToBorrow).debtShareToAmtCurrent(repayShares);
if (_poolToBorrow == _poolOut) {
// borrow with 10% buffer for price impact and swap fee
borrAmt = _getTokenAmt(_poolToBorrow, _poolToRepay, borrAmt) * 11_000 / 10_000;
} else if (_poolToBorrow != _poolToRepay) {
// borrow all available amt
borrAmt = IInitLens(LENS).modeBorrowableAmt(MODE, _poolToBorrow);
}
if (_poolToBorrow != _poolToRepay) {
// approve borrToken for flash borrow repayment
address borrToken = ILendingPool(_poolToBorrow).underlyingToken();
_ensureApprove(borrToken, CORE);
}
// 1. borrow token to repay debt
multicallData[0] =
abi.encodeWithSelector(IInitCore.borrow.selector, _poolToBorrow, borrAmt, PLACEHOLDER_ID, address(this));
}
// 2. callback to address(this) to swap borrToken to liquidate token (this will do nothing if borrToken == repayToken)
multicallData[1] = abi.encodeWithSelector(
IInitCore(CORE).callback.selector,
address(this),
0,
abi.encode(_router, _poolToBorrow, _poolToRepay, _posId, repayShares)
);
// 3. liquidate
multicallData[2] =
abi.encodeWithSelector(IInitCore.liquidate.selector, _posId, _poolToRepay, repayShares, _poolOut, 0);
// 4. callback to address(this) to burn _poolOut and swap to repay flash borrow
multicallData[3] = abi.encodeWithSelector(
IInitCore(CORE).callback.selector,
address(this),
0,
abi.encode(_router2, _poolOut, _poolToBorrow, PLACEHOLDER_ID, type(uint).max)
);
// 5. repay flash borrow
multicallData[4] = abi.encodeWithSelector(IInitCore.repay.selector, _poolToBorrow, MAX_UINT, PLACEHOLDER_ID);
IMulticall(CORE).multicall(multicallData);
}
function _getTokenAmt(address _poolToBorrow, address _poolToRepay, uint _repayAmt)
internal
view
returns (uint tokenAmt)
{
address tokenToBorrow = ILendingPool(_poolToBorrow).underlyingToken();
address tokenToRepay = ILendingPool(_poolToRepay).underlyingToken();
address oracle = IInitCore(CORE).oracle();
address[] memory tokens = new address[](2);
tokens[0] = tokenToBorrow;
tokens[1] = tokenToRepay;
uint[] memory prices_e36 = IInitOracle(oracle).getPrices_e36(tokens);
uint tokenToBorrowPrice_e36 = prices_e36[0];
uint tokenToRepayPrice_e36 = prices_e36[1];
tokenAmt = _repayAmt * tokenToRepayPrice_e36 / tokenToBorrowPrice_e36;
}
receive() external payable {}
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import {EnumerableSet} from '@openzeppelin-contracts/utils/structs/EnumerableSet.sol';
struct CollInfo {
address[] pools;
uint[] shares;
uint[] amts;
address[] wLps;
uint[][] ids;
uint[][] wLpAmts;
}
struct BorrInfo {
address[] pools;
uint[] debtShares;
uint[] debts;
}
struct PosInfo {
CollInfo collInfo;
BorrInfo borrInfo;
uint collCredit_e36;
uint borrCredit_e36;
uint health_e18;
uint16 mode;
address viewer;
address owner;
uint posId; // nft id
}
/// @title Init Lens Interface
interface IInitLens {
/// @dev get hook's user position info
/// @param _hook hook address
/// @param _user user address
/// @param _posId hook's position id
/// @return posInfo position info
function getHookPosInfo(address _hook, address _user, uint _posId) external returns (PosInfo memory posInfo);
/// @dev get hook's user position infos
/// @param _hook hook address
/// @param _user user address
/// @param _posIds hook's position ids
/// @return posInfos position infos
function getHookPosInfos(address _hook, address _user, uint[] calldata _posIds)
external
returns (PosInfo[] memory posInfos);
/// @dev get init position info
/// @param _initPosId init position id
/// @return posInfo position info
function getInitPosInfo(uint _initPosId) external returns (PosInfo memory posInfo);
/// @dev get init position infos
/// @param _initPosIds init position ids
/// @return posInfos position infos
function getInitPosInfos(uint[] calldata _initPosIds) external returns (PosInfo[] memory posInfos);
/// @dev get mode's pool borrowable amount
/// @param _mode mode
/// @param _pool pool address
/// @return borrowableAmt borrowable amount for the pool of the mode
function modeBorrowableAmt(uint16 _mode, address _pool) external returns (uint borrowableAmt);
/// @dev get position's pool borrowable amount
/// @param _hook hook address
/// @param _user user address
/// @param _posId hook's position id
/// @param _pool pool address
/// @return borrowableAmt borrowable amount for the pool of the position
function posBorrowableAmt(address _hook, address _user, uint _posId, address _pool)
external
returns (uint borrowableAmt);
/// @dev get position info from viewer with index
/// @param _viewer position viewer
/// @param _index viewer's index
/// @return posInfo position info
function viewerPosInfoAt(address _viewer, uint _index) external returns (PosInfo memory posInfo);
/// @dev get list of position info from viewer with list of indices
/// @param _viewer position viewer
/// @param _indices list of viewer's indices
/// @return posInfos list of position info
function viewerPosInfos(address _viewer, uint[] calldata _indices) external returns (PosInfo[] memory posInfos);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {IERC20} from '@openzeppelin-contracts/token/ERC20/IERC20.sol';
import {ILBFactory} from './ILBFactory.sol';
import {ILBFlashLoanCallback} from './ILBFlashLoanCallback.sol';
import {ILBToken} from './ILBToken.sol';
interface ILBPair is ILBToken {
error LBPair__ZeroBorrowAmount();
error LBPair__AddressZero();
error LBPair__AlreadyInitialized();
error LBPair__EmptyMarketConfigs();
error LBPair__FlashLoanCallbackFailed();
error LBPair__FlashLoanInsufficientAmount();
error LBPair__InsufficientAmountIn();
error LBPair__InsufficientAmountOut();
error LBPair__InvalidInput();
error LBPair__InvalidStaticFeeParameters();
error LBPair__OnlyFactory();
error LBPair__OnlyProtocolFeeRecipient();
error LBPair__OutOfLiquidity();
error LBPair__TokenNotSupported();
error LBPair__ZeroAmount(uint24 id);
error LBPair__ZeroAmountsOut(uint24 id);
error LBPair__ZeroShares(uint24 id);
error LBPair__MaxTotalFeeExceeded();
struct MintArrays {
uint[] ids;
bytes32[] amounts;
uint[] liquidityMinted;
}
event DepositedToBins(address indexed sender, address indexed to, uint[] ids, bytes32[] amounts);
event WithdrawnFromBins(address indexed sender, address indexed to, uint[] ids, bytes32[] amounts);
event CompositionFees(address indexed sender, uint24 id, bytes32 totalFees, bytes32 protocolFees);
event CollectedProtocolFees(address indexed feeRecipient, bytes32 protocolFees);
event Swap(
address indexed sender,
address indexed to,
uint24 id,
bytes32 amountsIn,
bytes32 amountsOut,
uint24 volatilityAccumulator,
bytes32 totalFees,
bytes32 protocolFees
);
event StaticFeeParametersSet(
address indexed sender,
uint16 baseFactor,
uint16 filterPeriod,
uint16 decayPeriod,
uint16 reductionFactor,
uint24 variableFeeControl,
uint16 protocolShare,
uint24 maxVolatilityAccumulator
);
event FlashLoan(
address indexed sender,
ILBFlashLoanCallback indexed receiver,
uint24 activeId,
bytes32 amounts,
bytes32 totalFees,
bytes32 protocolFees
);
event OracleLengthIncreased(address indexed sender, uint16 oracleLength);
event ForcedDecay(address indexed sender, uint24 idReference, uint24 volatilityReference);
function initialize(
uint16 baseFactor,
uint16 filterPeriod,
uint16 decayPeriod,
uint16 reductionFactor,
uint24 variableFeeControl,
uint16 protocolShare,
uint24 maxVolatilityAccumulator,
uint24 activeId
) external;
function getFactory() external view returns (ILBFactory factory);
function getTokenX() external view returns (IERC20 tokenX);
function getTokenY() external view returns (IERC20 tokenY);
function getBinStep() external view returns (uint16 binStep);
function getReserves() external view returns (uint128 reserveX, uint128 reserveY);
function getActiveId() external view returns (uint24 activeId);
function getBin(uint24 id) external view returns (uint128 binReserveX, uint128 binReserveY);
function getNextNonEmptyBin(bool swapForY, uint24 id) external view returns (uint24 nextId);
function getProtocolFees() external view returns (uint128 protocolFeeX, uint128 protocolFeeY);
function getStaticFeeParameters()
external
view
returns (
uint16 baseFactor,
uint16 filterPeriod,
uint16 decayPeriod,
uint16 reductionFactor,
uint24 variableFeeControl,
uint16 protocolShare,
uint24 maxVolatilityAccumulator
);
function getVariableFeeParameters()
external
view
returns (uint24 volatilityAccumulator, uint24 volatilityReference, uint24 idReference, uint40 timeOfLastUpdate);
function getOracleParameters()
external
view
returns (uint8 sampleLifetime, uint16 size, uint16 activeSize, uint40 lastUpdated, uint40 firstTimestamp);
function getOracleSampleAt(uint40 lookupTimestamp)
external
view
returns (uint64 cumulativeId, uint64 cumulativeVolatility, uint64 cumulativeBinCrossed);
function getPriceFromId(uint24 id) external view returns (uint price);
function getIdFromPrice(uint price) external view returns (uint24 id);
function getSwapIn(uint128 amountOut, bool swapForY)
external
view
returns (uint128 amountIn, uint128 amountOutLeft, uint128 fee);
function getSwapOut(uint128 amountIn, bool swapForY)
external
view
returns (uint128 amountInLeft, uint128 amountOut, uint128 fee);
function swap(bool swapForY, address to) external returns (bytes32 amountsOut);
function flashLoan(ILBFlashLoanCallback receiver, bytes32 amounts, bytes calldata data) external;
function mint(address to, bytes32[] calldata liquidityConfigs, address refundTo)
external
returns (bytes32 amountsReceived, bytes32 amountsLeft, uint[] memory liquidityMinted);
function burn(address from, address to, uint[] calldata ids, uint[] calldata amountsToBurn)
external
returns (bytes32[] memory amounts);
function collectProtocolFees() external returns (bytes32 collectedProtocolFees);
function increaseOracleLength(uint16 newLength) external;
function setStaticFeeParameters(
uint16 baseFactor,
uint16 filterPeriod,
uint16 decayPeriod,
uint16 reductionFactor,
uint24 variableFeeControl,
uint16 protocolShare,
uint24 maxVolatilityAccumulator
) external;
function forceDecay() external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {IERC20} from '@openzeppelin-contracts/token/ERC20/IERC20.sol';
import {ILBFactory} from './ILBFactory.sol';
import {IJoeFactory} from './IJoeFactory.sol';
import {ILBLegacyPair} from './ILBLegacyPair.sol';
import {ILBToken} from './ILBToken.sol';
import {IWNative} from '../IWNative.sol';
/// @title Liquidity Book Router Interface
/// @author Trader Joe
/// @notice Required interface of LBRouter contract
interface ILBLegacyRouter {
struct LiquidityParameters {
IERC20 tokenX;
IERC20 tokenY;
uint binStep;
uint amountX;
uint amountY;
uint amountXMin;
uint amountYMin;
uint activeIdDesired;
uint idSlippage;
int[] deltaIds;
uint[] distributionX;
uint[] distributionY;
address to;
uint deadline;
}
function factory() external view returns (address);
function wavax() external view returns (address);
function oldFactory() external view returns (address);
function getIdFromPrice(ILBLegacyPair LBPair, uint price) external view returns (uint24);
function getPriceFromId(ILBLegacyPair LBPair, uint24 id) external view returns (uint);
function getSwapIn(ILBLegacyPair lbPair, uint amountOut, bool swapForY)
external
view
returns (uint amountIn, uint feesIn);
function getSwapOut(ILBLegacyPair lbPair, uint amountIn, bool swapForY)
external
view
returns (uint amountOut, uint feesIn);
function createLBPair(IERC20 tokenX, IERC20 tokenY, uint24 activeId, uint16 binStep)
external
returns (ILBLegacyPair pair);
function addLiquidity(LiquidityParameters calldata liquidityParameters)
external
returns (uint[] memory depositIds, uint[] memory liquidityMinted);
function addLiquidityAVAX(LiquidityParameters calldata liquidityParameters)
external
payable
returns (uint[] memory depositIds, uint[] memory liquidityMinted);
function removeLiquidity(
IERC20 tokenX,
IERC20 tokenY,
uint16 binStep,
uint amountXMin,
uint amountYMin,
uint[] memory ids,
uint[] memory amounts,
address to,
uint deadline
) external returns (uint amountX, uint amountY);
function removeLiquidityAVAX(
IERC20 token,
uint16 binStep,
uint amountTokenMin,
uint amountAVAXMin,
uint[] memory ids,
uint[] memory amounts,
address payable to,
uint deadline
) external returns (uint amountToken, uint amountAVAX);
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
uint[] memory pairBinSteps,
IERC20[] memory tokenPath,
address to,
uint deadline
) external returns (uint amountOut);
function swapExactTokensForAVAX(
uint amountIn,
uint amountOutMinAVAX,
uint[] memory pairBinSteps,
IERC20[] memory tokenPath,
address payable to,
uint deadline
) external returns (uint amountOut);
function swapExactAVAXForTokens(
uint amountOutMin,
uint[] memory pairBinSteps,
IERC20[] memory tokenPath,
address to,
uint deadline
) external payable returns (uint amountOut);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
uint[] memory pairBinSteps,
IERC20[] memory tokenPath,
address to,
uint deadline
) external returns (uint[] memory amountsIn);
function swapTokensForExactAVAX(
uint amountOut,
uint amountInMax,
uint[] memory pairBinSteps,
IERC20[] memory tokenPath,
address payable to,
uint deadline
) external returns (uint[] memory amountsIn);
function swapAVAXForExactTokens(
uint amountOut,
uint[] memory pairBinSteps,
IERC20[] memory tokenPath,
address to,
uint deadline
) external payable returns (uint[] memory amountsIn);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
uint[] memory pairBinSteps,
IERC20[] memory tokenPath,
address to,
uint deadline
) external returns (uint amountOut);
function swapExactTokensForAVAXSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMinAVAX,
uint[] memory pairBinSteps,
IERC20[] memory tokenPath,
address payable to,
uint deadline
) external returns (uint amountOut);
function swapExactAVAXForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
uint[] memory pairBinSteps,
IERC20[] memory tokenPath,
address to,
uint deadline
) external payable returns (uint amountOut);
function sweep(IERC20 token, address to, uint amount) external;
function sweepLBToken(ILBToken _lbToken, address _to, uint[] calldata _ids, uint[] calldata _amounts) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)
pragma solidity ^0.8.0;
/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/
interface IERC721Receiver {
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import {IBaseOracle} from './IBaseOracle.sol';
/// @title Init Oracle Interface
interface IInitOracle is IBaseOracle {
event SetPrimarySource(address indexed token, address oracle);
event SetSecondarySource(address indexed token, address oracle);
event SetMaxPriceDeviation_e18(address indexed token, uint maxPriceDeviation_e18);
/// @dev return the oracle token's primary source
/// @param _token token address
/// @return primarySource primary oracle address
function primarySources(address _token) external view returns (address primarySource);
/// @dev return the oracle token's secondary source
/// @param _token token address
/// @return secondarySource secoundary oracle address
function secondarySources(address _token) external view returns (address secondarySource);
/// @dev return the max price deviation between the primary and secondary sources
/// @param _token token address
/// @return maxPriceDeviation_e18 max price deviation in 1e18
function maxPriceDeviations_e18(address _token) external view returns (uint maxPriceDeviation_e18);
/// @dev return the price of the tokens in USD, multiplied by 1e36.
/// @param _tokens token address list
/// @return prices_e36 the token prices for each tokens
function getPrices_e36(address[] calldata _tokens) external view returns (uint[] memory prices_e36);
/// @dev set primary source for tokens
/// @param _tokens token address list
/// @param _sources the primary source address for each tokens
function setPrimarySources(address[] calldata _tokens, address[] calldata _sources) external;
/// @dev set secondary source for tokens
/// @param _tokens token address list
/// @param _sources the secondary source address for each tokens
function setSecondarySources(address[] calldata _tokens, address[] calldata _sources) external;
/// @dev set max price deviation between the primary and sercondary sources
/// @param _tokens token address list
/// @param _maxPriceDeviations_e18 the max price deviation in 1e18 for each tokens
function setMaxPriceDeviations_e18(address[] calldata _tokens, uint[] calldata _maxPriceDeviations_e18) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {IERC20} from '@openzeppelin-contracts/token/ERC20/IERC20.sol';
import {IJoeFactory} from './IJoeFactory.sol';
import {ILBFactory} from './ILBFactory.sol';
import {ILBLegacyFactory} from './ILBLegacyFactory.sol';
import {ILBLegacyRouter} from './ILBLegacyRouter.sol';
import {ILBPair} from './ILBPair.sol';
import {ILBToken} from './ILBToken.sol';
import {IWNative} from '../IWNative.sol';
/**
* @title Liquidity Book Router Interface
* @author Trader Joe
* @notice Required interface of LBRouter contract
*/
interface ILBRouter {
error LBRouter__SenderIsNotWNATIVE();
error LBRouter__PairNotCreated(address tokenX, address tokenY, uint binStep);
error LBRouter__WrongAmounts(uint amount, uint reserve);
error LBRouter__SwapOverflows(uint id);
error LBRouter__BrokenSwapSafetyCheck();
error LBRouter__NotFactoryOwner();
error LBRouter__TooMuchTokensIn(uint excess);
error LBRouter__BinReserveOverflows(uint id);
error LBRouter__IdOverflows(int id);
error LBRouter__LengthsMismatch();
error LBRouter__WrongTokenOrder();
error LBRouter__IdSlippageCaught(uint activeIdDesired, uint idSlippage, uint activeId);
error LBRouter__AmountSlippageCaught(uint amountXMin, uint amountX, uint amountYMin, uint amountY);
error LBRouter__IdDesiredOverflows(uint idDesired, uint idSlippage);
error LBRouter__FailedToSendNATIVE(address recipient, uint amount);
error LBRouter__DeadlineExceeded(uint deadline, uint currentTimestamp);
error LBRouter__AmountSlippageBPTooBig(uint amountSlippage);
error LBRouter__InsufficientAmountOut(uint amountOutMin, uint amountOut);
error LBRouter__MaxAmountInExceeded(uint amountInMax, uint amountIn);
error LBRouter__InvalidTokenPath(address wrongToken);
error LBRouter__InvalidVersion(uint version);
error LBRouter__WrongNativeLiquidityParameters(
address tokenX, address tokenY, uint amountX, uint amountY, uint msgValue
);
/**
* @dev This enum represents the version of the pair requested
* - V1: Joe V1 pair
* - V2: LB pair V2. Also called legacyPair
* - V2_1: LB pair V2.1 (current version)
*/
enum Version {
V1,
V2,
V2_1
}
/**
* @dev The liquidity parameters, such as:
* - tokenX: The address of token X
* - tokenY: The address of token Y
* - binStep: The bin step of the pair
* - amountX: The amount to send of token X
* - amountY: The amount to send of token Y
* - amountXMin: The min amount of token X added to liquidity
* - amountYMin: The min amount of token Y added to liquidity
* - activeIdDesired: The active id that user wants to add liquidity from
* - idSlippage: The number of id that are allowed to slip
* - deltaIds: The list of delta ids to add liquidity (`deltaId = activeId - desiredId`)
* - distributionX: The distribution of tokenX with sum(distributionX) = 1e18 (100%) or 0 (0%)
* - distributionY: The distribution of tokenY with sum(distributionY) = 1e18 (100%) or 0 (0%)
* - to: The address of the recipient
* - refundTo: The address of the recipient of the refunded tokens if too much tokens are sent
* - deadline: The deadline of the transaction
*/
struct LiquidityParameters {
IERC20 tokenX;
IERC20 tokenY;
uint binStep;
uint amountX;
uint amountY;
uint amountXMin;
uint amountYMin;
uint activeIdDesired;
uint idSlippage;
int[] deltaIds;
uint[] distributionX;
uint[] distributionY;
address to;
address refundTo;
uint deadline;
}
/**
* @dev The path parameters, such as:
* - pairBinSteps: The list of bin steps of the pairs to go through
* - versions: The list of versions of the pairs to go through
* - tokenPath: The list of tokens in the path to go through
*/
struct Path {
uint[] pairBinSteps;
Version[] versions;
IERC20[] tokenPath;
}
function getFactory() external view returns (ILBFactory);
function getLegacyFactory() external view returns (ILBLegacyFactory);
function getV1Factory() external view returns (IJoeFactory);
function getLegacyRouter() external view returns (ILBLegacyRouter);
function getWNATIVE() external view returns (IWNative);
function getIdFromPrice(ILBPair LBPair, uint price) external view returns (uint24);
function getPriceFromId(ILBPair LBPair, uint24 id) external view returns (uint);
function getSwapIn(ILBPair LBPair, uint128 amountOut, bool swapForY)
external
view
returns (uint128 amountIn, uint128 amountOutLeft, uint128 fee);
function getSwapOut(ILBPair LBPair, uint128 amountIn, bool swapForY)
external
view
returns (uint128 amountInLeft, uint128 amountOut, uint128 fee);
function createLBPair(IERC20 tokenX, IERC20 tokenY, uint24 activeId, uint16 binStep)
external
returns (ILBPair pair);
function addLiquidity(LiquidityParameters calldata liquidityParameters)
external
returns (
uint amountXAdded,
uint amountYAdded,
uint amountXLeft,
uint amountYLeft,
uint[] memory depositIds,
uint[] memory liquidityMinted
);
function addLiquidityNATIVE(LiquidityParameters calldata liquidityParameters)
external
payable
returns (
uint amountXAdded,
uint amountYAdded,
uint amountXLeft,
uint amountYLeft,
uint[] memory depositIds,
uint[] memory liquidityMinted
);
function removeLiquidity(
IERC20 tokenX,
IERC20 tokenY,
uint16 binStep,
uint amountXMin,
uint amountYMin,
uint[] memory ids,
uint[] memory amounts,
address to,
uint deadline
) external returns (uint amountX, uint amountY);
function removeLiquidityNATIVE(
IERC20 token,
uint16 binStep,
uint amountTokenMin,
uint amountNATIVEMin,
uint[] memory ids,
uint[] memory amounts,
address payable to,
uint deadline
) external returns (uint amountToken, uint amountNATIVE);
function swapExactTokensForTokens(uint amountIn, uint amountOutMin, Path memory path, address to, uint deadline)
external
returns (uint amountOut);
function swapExactTokensForNATIVE(
uint amountIn,
uint amountOutMinNATIVE,
Path memory path,
address payable to,
uint deadline
) external returns (uint amountOut);
function swapExactNATIVEForTokens(uint amountOutMin, Path memory path, address to, uint deadline)
external
payable
returns (uint amountOut);
function swapTokensForExactTokens(uint amountOut, uint amountInMax, Path memory path, address to, uint deadline)
external
returns (uint[] memory amountsIn);
function swapTokensForExactNATIVE(
uint amountOut,
uint amountInMax,
Path memory path,
address payable to,
uint deadline
) external returns (uint[] memory amountsIn);
function swapNATIVEForExactTokens(uint amountOut, Path memory path, address to, uint deadline)
external
payable
returns (uint[] memory amountsIn);
function swapExactTokensForTokensSupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMin,
Path memory path,
address to,
uint deadline
) external returns (uint amountOut);
function swapExactTokensForNATIVESupportingFeeOnTransferTokens(
uint amountIn,
uint amountOutMinNATIVE,
Path memory path,
address payable to,
uint deadline
) external returns (uint amountOut);
function swapExactNATIVEForTokensSupportingFeeOnTransferTokens(
uint amountOutMin,
Path memory path,
address to,
uint deadline
) external payable returns (uint amountOut);
function sweep(IERC20 token, address to, uint amount) external;
function sweepLBToken(ILBToken _lbToken, address _to, uint[] calldata _ids, uint[] calldata _amounts) external;
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
/// @title Base Oracle Interface
interface IBaseOracle {
/// @dev return the value of the token as USD, multiplied by 1e36.
/// @param _token token address
/// @return price_e36 token price in 1e36
function getPrice_e36(address _token) external view returns (uint price_e36);
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
library UncheckedIncrement {
function uinc(uint self) internal pure returns (uint) {
unchecked {
return self + 1;
}
}
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
/// @title Liquidation Incentive Calculator Interface
interface ILiqIncentiveCalculator {
event SetModeLiqIncentiveMultiplier_e18(uint16[] modes, uint[] multipliers_e18);
event SetTokenLiqIncentiveMultiplier_e18(address[] tokens, uint[] multipliers_e18);
event SetMaxLiqIncentiveMultiplier_e18(uint maxIncentiveMultiplier_e18);
event SetMinLiqIncentiveMultiplier_e18(uint16[] modes, uint[] minIncentiveMultipliers_e18);
/// @notice the minimum capped value for the liquidation incentive multiplier
/// @dev get the min incentive multiplier
/// @dev _mode position mode
/// @return minLiqIncentiveMultiplier_e18 min incentive multiplier in 1e18
function minLiqIncentiveMultiplier_e18(uint16 _mode) external returns (uint minLiqIncentiveMultiplier_e18);
/// @notice the maximum capped value for the liquidation incentive multiplier
/// @dev get the max incentive multiplier
/// @return maxLiqIncentiveMultiplier_e18 max incentive multiplier in 1e18
function maxLiqIncentiveMultiplier_e18() external returns (uint maxLiqIncentiveMultiplier_e18);
/// @dev get the mode liquidation incentive multiplier
/// @param _mode position mode
/// @return modeLiqIncentiveMultiplier_e18 mode incentive multiplier in 1e18
function modeLiqIncentiveMultiplier_e18(uint16 _mode) external returns (uint modeLiqIncentiveMultiplier_e18);
/// @dev get the liquidation incentive multiplier for the token
/// @param _token token address
/// @return tokenLiqIncentiveMultiplier_e18 token incentive multiplier in 1e18
function tokenLiqIncentiveMultiplier_e18(address _token) external returns (uint tokenLiqIncentiveMultiplier_e18);
/// @dev calculate the liquidation incentive multiplier, given the position's mode, health factor and repay and collateral tokens
/// @param _mode position mode
/// @param _healthFactor_e18 position current health factor in 1e18
/// @param _repayToken repay token's underlying
/// @param _collToken receive token's underlying
/// @return multiplier_e18 liquidation incentive multiplier in 1e18
function getLiqIncentiveMultiplier_e18(
uint16 _mode,
uint _healthFactor_e18,
address _repayToken,
address _collToken
) external view returns (uint multiplier_e18);
/// @dev set the liquidation incentive multipliers for position modes
/// @param _modes position mode id list
/// @param _multipliers_e18 new mode liquidation incentive multiplier list in 1e18 to set to
function setModeLiqIncentiveMultiplier_e18(uint16[] calldata _modes, uint[] calldata _multipliers_e18) external;
/// @dev set the liquidation incentive multipliers for tokens
/// @param _tokens token list
/// @param _multipliers_e18 new token liquidation incentive multiplier list in 1e18 to set to
function setTokenLiqIncentiveMultiplier_e18(address[] calldata _tokens, uint[] calldata _multipliers_e18)
external;
/// @dev set the max liquidation incentive multiplier
/// @param _maxLiqIncentiveMultiplier_e18 new max liquidation incentive multiplier in 1e18
function setMaxLiqIncentiveMultiplier_e18(uint _maxLiqIncentiveMultiplier_e18) external;
/// @dev set the min liquidation incentive multiplier
/// @param _modes position mode id list
/// @param _minMultipliers_e18 new min liquidation incentive multiplier in 1e18
function setMinLiqIncentiveMultiplier_e18(uint16[] calldata _modes, uint[] calldata _minMultipliers_e18) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import './ISwapDataEncoder.sol';
interface ISwapDataRegistry {
// events
event SetSwapEncoder(address swapEncoder);
event SetSwapInfo(address tokenIn, address tokenOut, address router, bytes infos);
event SetRouterType(address router, uint routerType);
// functions
function getCalldata(
address sender,
address _tokenIn,
address _tokenOut,
SwapOperation _operation,
address _router,
uint _amount
) external view returns (bytes memory);
function setSwapInfos(
address[] calldata _tokenIns,
address[] calldata _tokenOuts,
address[] calldata _routers,
bytes[] calldata _infos
) external;
function setSwapEncoder(address _swapEncoder) external;
function routerTypes(address _router) external view returns (uint);
function swapInfos(address _tokenIn, address _tokenOut, address _router) external view returns (bytes memory);
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import {EnumerableSet} from '@openzeppelin-contracts/utils/structs/EnumerableSet.sol';
// structs
struct TokenFactors {
uint128 collFactor_e18; // collateral factor in 1e18 (1e18 = 100%)
uint128 borrFactor_e18; // borrow factor in 1e18 (1e18 = 100%)
}
struct ModeConfig {
EnumerableSet.AddressSet collTokens; // enumerable set of collateral tokens
EnumerableSet.AddressSet borrTokens; // enumerable set of borrow tokens
uint64 maxHealthAfterLiq_e18; // max health factor allowed after liquidation
mapping(address => TokenFactors) factors; // token factors mapping
ModeStatus status; // mode status
uint8 maxCollWLpCount; // limit number of wLp to avoid out of gas
}
struct PoolConfig {
uint128 supplyCap; // pool supply cap
uint128 borrowCap; // pool borrow cap
bool canMint; // pool mint status
bool canBurn; // pool burn status
bool canBorrow; // pool borrow status
bool canRepay; // pool repay status
bool canFlash; // pool flash status
}
struct ModeStatus {
bool canCollateralize; // mode collateralize status
bool canDecollateralize; // mode decollateralize status
bool canBorrow; // mode borrow status
bool canRepay; // mode repay status
}
/// @title Config Interface
/// @notice Configuration parameters for the protocol.
interface IConfig {
event SetPoolConfig(address indexed pool, PoolConfig config);
event SetCollFactors_e18(uint16 indexed mode, address[] tokens, uint128[] _factors);
event SetBorrFactors_e18(uint16 indexed mode, address[] tokens, uint128[] factors);
event SetMaxHealthAfterLiq_e18(uint16 indexed mode, uint64 maxHealthAfterLiq_e18);
event SetWhitelistedWLps(address[] wLps, bool status);
event SetModeStatus(uint16 mode, ModeStatus status);
event SetMaxCollWLpCount(uint16 indexed mode, uint8 maxCollWLpCount);
/// @dev check if the wrapped lp is whitelisted.
/// @param _wlp wrapped lp address
/// @return whether the wrapped lp is whitelisted.
function whitelistedWLps(address _wlp) external view returns (bool);
/// @dev get mode config
/// @param _mode mode id
/// @return collTokens collateral token list
/// borrTokens borrow token list
/// maxHealthAfterLiq_e18 max health factor allowed after liquidation
/// maxCollWLpCount // limit number of wLp to avoid out of gas
function getModeConfig(uint16 _mode)
external
view
returns (
address[] memory collTokens,
address[] memory borrTokens,
uint maxHealthAfterLiq_e18,
uint8 maxCollWLpCount
);
/// @dev get pool config
/// @param _pool pool address
/// @return poolConfig pool config
function getPoolConfig(address _pool) external view returns (PoolConfig memory poolConfig);
/// @dev check if the pool within the specified mode is allowed for borrowing.
/// @param _mode mode id
/// @param _pool lending pool address
/// @return whether the pool within the mode is allowed for borrowing.
function isAllowedForBorrow(uint16 _mode, address _pool) external view returns (bool);
/// @dev check if the pool within the specified mode is allowed for collateralizing.
/// @param _mode mode id
/// @param _pool lending pool address
/// @return whether the pool within the mode is allowed for collateralizing.
function isAllowedForCollateral(uint16 _mode, address _pool) external view returns (bool);
/// @dev get the token factors (collateral and borrow factors)
/// @param _mode mode id
/// @param _pool lending pool address
/// @return tokenFactors token factors
function getTokenFactors(uint16 _mode, address _pool) external view returns (TokenFactors memory tokenFactors);
/// @notice if return the value of type(uint64).max, skip the health check after liquidation
/// @dev get the mode max health allowed after liquidation
/// @param _mode mode id
/// @param maxHealthAfterLiq_e18 max allowed health factor after liquidation
function getMaxHealthAfterLiq_e18(uint16 _mode) external view returns (uint maxHealthAfterLiq_e18);
/// @dev get the current mode status
/// @param _mode mode id
/// @return modeStatus mode status (collateralize, decollateralize, borrow or repay)
function getModeStatus(uint16 _mode) external view returns (ModeStatus memory modeStatus);
/// @dev set pool config
/// @param _pool lending pool address
/// @param _config new pool config
function setPoolConfig(address _pool, PoolConfig calldata _config) external;
/// @dev set pool collateral factors
/// @param _pools lending pool address list
/// @param _factors new collateral factor list in 1e18 (1e18 = 100%)
function setCollFactors_e18(uint16 _mode, address[] calldata _pools, uint128[] calldata _factors) external;
/// @dev set pool borrow factors
/// @param _pools lending pool address list
/// @param _factors new borrow factor list in 1e18 (1e18 = 100%)
function setBorrFactors_e18(uint16 _mode, address[] calldata _pools, uint128[] calldata _factors) external;
/// @dev set mode status
/// @param _status new mode status to set to (collateralize, decollateralize, borrow and repay)
function setModeStatus(uint16 _mode, ModeStatus calldata _status) external;
/// @notice only governor role can call
/// @dev set whitelisted wrapped lp statuses
/// @param _wLps wrapped lp list
/// @param _status whitelisted status to set to
function setWhitelistedWLps(address[] calldata _wLps, bool _status) external;
/// @dev set max health after liquidation (type(uint64).max means infinite, or no check)
/// @param _mode mode id
/// @param _maxHealthAfterLiq_e18 new max allowed health factor after liquidation
function setMaxHealthAfterLiq_e18(uint16 _mode, uint64 _maxHealthAfterLiq_e18) external;
/// @dev set mode's max collateral wrapped lp count to avoid out of gas
/// @param _mode mode id
/// @param _maxCollWLpCount max collateral wrapped lp count
function setMaxCollWLpCount(uint16 _mode, uint8 _maxCollWLpCount) external;
/// @dev get mode's max collateral wlp count
/// @param _mode mode id
/// @return the mode's max collateral wlp count
function getModeMaxCollWLpCount(uint16 _mode) external view returns (uint8);
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import './IConfig.sol';
/// @title InitCore Interface
interface IInitCore {
event SetConfig(address indexed newConfig);
event SetOracle(address indexed newOracle);
event SetIncentiveCalculator(address indexed newIncentiveCalculator);
event SetRiskManager(address indexed newRiskManager);
event Borrow(address indexed pool, uint indexed posId, address indexed to, uint borrowAmt, uint shares);
event Repay(address indexed pool, uint indexed posId, address indexed repayer, uint shares, uint amtToRepay);
event CreatePosition(address indexed owner, uint indexed posId, uint16 mode, address viewer);
event SetPositionMode(uint indexed posId, uint16 mode);
event Collateralize(uint indexed posId, address indexed pool, uint amt);
event Decollateralize(uint indexed posId, address indexed pool, address indexed to, uint amt);
event CollateralizeWLp(uint indexed posId, address indexed wLp, uint indexed tokenId, uint amt);
event DecollateralizeWLp(uint indexed posId, address indexed wLp, uint indexed tokenId, address to, uint amt);
event Liquidate(uint indexed posId, address indexed liquidator, address poolOut, uint shares);
event LiquidateWLp(uint indexed posId, address indexed liquidator, address wLpOut, uint tokenId, uint amt);
struct LiquidateLocalVars {
IConfig config;
uint16 mode;
uint health_e18;
uint liqIncentive_e18;
address collToken;
address repayToken;
uint repayAmt;
uint repayAmtWithLiqIncentive;
}
/// @dev get position manager address
function POS_MANAGER() external view returns (address);
/// @dev get config address
function config() external view returns (address);
/// @dev get oracle address
function oracle() external view returns (address);
/// @dev get risk manager address
function riskManager() external view returns (address);
/// @dev get liquidation incentive calculator address
function liqIncentiveCalculator() external view returns (address);
/// @dev mint lending pool shares (using ∆balance in lending pool)
/// @param _pool lending pool address
/// @param _to address to receive share token
/// @return shares amount of share tokens minted
function mintTo(address _pool, address _to) external returns (uint shares);
/// @dev burn lending pool share tokens to receive underlying (using ∆balance in lending pool)
/// @param _pool lending pool address
/// @param _to address to receive underlying
/// @return amt amount of underlying to receive
function burnTo(address _pool, address _to) external returns (uint amt);
/// @dev borrow underlying from lending pool
/// @param _pool lending pool address
/// @param _amt amount of underlying to borrow
/// @param _posId position id to account for the borrowing
/// @param _to address to receive borrow underlying
/// @return shares the amount of debt shares for the borrowing
function borrow(address _pool, uint _amt, uint _posId, address _to) external returns (uint shares);
/// @dev repay debt to the lending pool
/// @param _pool address of lending pool
/// @param _shares debt shares to repay
/// @param _posId position id to repay debt
/// @return amt amount of underlying to repaid
function repay(address _pool, uint _shares, uint _posId) external returns (uint amt);
/// @dev create a new position
/// @param _mode position mode
/// @param _viewer position viewer address
function createPos(uint16 _mode, address _viewer) external returns (uint posId);
/// @dev change a position's mode
/// @param _posId position id to change mode
/// @param _mode position mode to change to
function setPosMode(uint _posId, uint16 _mode) external;
/// @dev collateralize lending pool share tokens to position
/// @param _posId position id to collateralize to
/// @param _pool lending pool address
function collateralize(uint _posId, address _pool) external;
/// @notice need to check the position's health after decollateralization
/// @dev decollateralize lending pool share tokens from the position
/// @param _posId position id to decollateral
/// @param _pool lending pool address
/// @param _shares amount of share tokens to decollateralize
/// @param _to address to receive token
function decollateralize(uint _posId, address _pool, uint _shares, address _to) external;
/// @dev collateralize wlp to position
/// @param _posId position id to collateralize to
/// @param _wLp wlp token address
/// @param _tokenId token id of wlp token to collateralize
function collateralizeWLp(uint _posId, address _wLp, uint _tokenId) external;
/// @notice need to check position's health after decollateralization
/// @dev decollateralize wlp from the position
/// @param _posId position id to decollateralize
/// @param _wLp wlp token address
/// @param _tokenId token id of wlp token to decollateralize
/// @param _amt amount of wlp token to decollateralize
function decollateralizeWLp(uint _posId, address _wLp, uint _tokenId, uint _amt, address _to) external;
/// @notice need to check position's health before liquidate & limit health after liqudate
/// @dev (partial) liquidate the position
/// @param _posId position id to liquidate
/// @param _poolToRepay address of lending pool to liquidate
/// @param _repayShares debt shares to repay
/// @param _tokenOut pool token to receive for the liquidation
/// @param _minShares min amount of pool token to receive after liquidate (slippage control)
/// @return amt the token amount out actually transferred out
function liquidate(uint _posId, address _poolToRepay, uint _repayShares, address _tokenOut, uint _minShares)
external
returns (uint amt);
/// @notice need to check position's health before liquidate & limit health after liqudate
/// @dev (partial) liquidate the position
/// @param _posId position id to liquidate
/// @param _poolToRepay address of lending pool to liquidate
/// @param _repayShares debt shares to liquidate
/// @param _wLp wlp to unwrap for liquidation
/// @param _tokenId wlp token id to burn for liquidation
/// @param _minLpOut min amount of lp to receive for liquidation
/// @return amt the token amount out actually transferred out
function liquidateWLp(
uint _posId,
address _poolToRepay,
uint _repayShares,
address _wLp,
uint _tokenId,
uint _minLpOut
) external returns (uint amt);
/// @notice caller must implement `flashCallback` function
/// @dev flashloan underlying tokens from lending pool
/// @param _pools lending pool address list to flashloan from
/// @param _amts token amount list to flashloan
/// @param _data data to execute in the callback function
function flash(address[] calldata _pools, uint[] calldata _amts, bytes calldata _data) external;
/// @dev make a callback to the target contract
/// @param _to target address to receive callback
/// @param _value msg.value to pass on to the callback
/// @param _data data to execute callback function
/// @return result callback result
function callback(address _to, uint _value, bytes calldata _data) external payable returns (bytes memory result);
/// @notice this is NOT a view function
/// @dev get current position's collateral credit in 1e36 (interest accrued up to current timestamp)
/// @param _posId position id to get collateral credit for
/// @return credit current position collateral credit
function getCollateralCreditCurrent_e36(uint _posId) external returns (uint credit);
/// @dev get current position's borrow credit in 1e36 (interest accrued up to current timestamp)
/// @param _posId position id to get borrow credit for
/// @return credit current position borrow credit
function getBorrowCreditCurrent_e36(uint _posId) external returns (uint credit);
/// @dev get current position's health factor in 1e18 (interest accrued up to current timestamp)
/// @param _posId position id to get health factor
/// @return health current position health factor
function getPosHealthCurrent_e18(uint _posId) external returns (uint health);
/// @dev set new config
function setConfig(address _config) external;
/// @dev set new oracle
function setOracle(address _oracle) external;
/// @dev set new liquidation incentve calculator
function setLiqIncentiveCalculator(address _liqIncentiveCalculator) external;
/// @dev set new risk manager
function setRiskManager(address _riskManager) external;
/// @dev transfer token from msg.sender to the target address
/// @param _token token address to transfer
/// @param _to address to receive token
/// @param _amt amount of token to transfer
function transferToken(address _token, address _to, uint _amt) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import '@openzeppelin-contracts/utils/introspection/IERC165.sol';
/// @title Liquidity Book V2 Token Interface
/// @author Trader Joe
/// @notice Required interface of LBToken contract
interface ILBLegacyToken is IERC165 {
event TransferSingle(address indexed sender, address indexed from, address indexed to, uint id, uint amount);
event TransferBatch(address indexed sender, address indexed from, address indexed to, uint[] ids, uint[] amounts);
event ApprovalForAll(address indexed account, address indexed sender, bool approved);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function balanceOf(address account, uint id) external view returns (uint);
function balanceOfBatch(address[] calldata accounts, uint[] calldata ids)
external
view
returns (uint[] memory batchBalances);
function totalSupply(uint id) external view returns (uint);
function isApprovedForAll(address owner, address spender) external view returns (bool);
function setApprovalForAll(address sender, bool approved) external;
function safeTransferFrom(address from, address to, uint id, uint amount) external;
function safeBatchTransferFrom(address from, address to, uint[] calldata id, uint[] calldata amount) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {IERC20} from '@openzeppelin-contracts/token/ERC20/IERC20.sol';
import {ILBLegacyToken} from './ILBLegacyToken.sol';
/// @title Liquidity Book Pair V2 Interface
/// @author Trader Joe
/// @notice Required interface of LBPair contract
interface ILBLegacyPair is ILBLegacyToken {
/// @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;
}
/// @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;
uint accTokenXPerShare;
uint 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;
FeesDistribution feesX;
FeesDistribution feesY;
}
/// @dev Structure to store the debts of users
/// - debtX: The tokenX's debt
/// - debtY: The tokenY's debt
struct Debts {
uint debtX;
uint 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 {
uint amountXIn;
uint amountYIn;
uint amountXAddedToPair;
uint amountYAddedToPair;
uint activeFeeX;
uint activeFeeY;
uint totalDistributionX;
uint totalDistributionY;
uint id;
uint amountX;
uint amountY;
uint distributionX;
uint distributionY;
}
event Swap(
address indexed sender,
address indexed recipient,
uint indexed id,
bool swapForY,
uint amountIn,
uint amountOut,
uint volatilityAccumulated,
uint fees
);
event FlashLoan(address indexed sender, address indexed receiver, IERC20 token, uint amount, uint fee);
event CompositionFee(address indexed sender, address indexed recipient, uint indexed id, uint feesX, uint feesY);
event DepositedToBin(
address indexed sender, address indexed recipient, uint indexed id, uint amountX, uint amountY
);
event WithdrawnFromBin(
address indexed sender, address indexed recipient, uint indexed id, uint amountX, uint amountY
);
event FeesCollected(address indexed sender, address indexed recipient, uint amountX, uint amountY);
event ProtocolFeesCollected(address indexed sender, address indexed recipient, uint amountX, uint amountY);
event OracleSizeIncreased(uint previousSize, uint newSize);
function tokenX() external view returns (IERC20);
function tokenY() external view returns (IERC20);
function factory() external view returns (address);
function getReservesAndId() external view returns (uint reserveX, uint reserveY, uint activeId);
function getGlobalFees()
external
view
returns (uint128 feesXTotal, uint128 feesYTotal, uint128 feesXProtocol, uint128 feesYProtocol);
function getOracleParameters()
external
view
returns (
uint oracleSampleLifetime,
uint oracleSize,
uint oracleActiveSize,
uint oracleLastTimestamp,
uint oracleId,
uint min,
uint max
);
function getOracleSampleFrom(uint timeDelta)
external
view
returns (uint cumulativeId, uint cumulativeAccumulator, uint cumulativeBinCrossed);
function feeParameters() external view returns (FeeParameters memory);
function findFirstNonEmptyBinId(uint24 id_, bool sentTokenY) external view returns (uint24 id);
function getBin(uint24 id) external view returns (uint reserveX, uint reserveY);
function pendingFees(address account, uint[] memory ids) external view returns (uint amountX, uint amountY);
function swap(bool sentTokenY, address to) external returns (uint amountXOut, uint amountYOut);
function flashLoan(address receiver, IERC20 token, uint amount, bytes calldata data) external;
function mint(uint[] calldata ids, uint[] calldata distributionX, uint[] calldata distributionY, address to)
external
returns (uint amountXAddedToPair, uint amountYAddedToPair, uint[] memory liquidityMinted);
function burn(uint[] calldata ids, uint[] calldata amounts, address to)
external
returns (uint amountX, uint amountY);
function increaseOracleLength(uint16 newSize) external;
function collectFees(address account, uint[] calldata ids) external returns (uint amountX, uint 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: None
pragma solidity ^0.8.19;
import {IERC20} from '@openzeppelin-contracts/token/ERC20/IERC20.sol';
/// @title Wrapped Native Interface
interface IWNative is IERC20 {
/// @dev wrap the native token to wrapped token using `msg.value` as the amount
function deposit() external payable;
/// @dev unwrap the wrapped token to native token
/// @param amount token amount to unwrap
function withdraw(uint amount) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
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.
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position 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) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
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 {
error PendingOwnable__AddressZero();
error PendingOwnable__NoPendingOwner();
error PendingOwnable__NotOwner();
error PendingOwnable__NotPendingOwner();
error PendingOwnable__PendingOwnerAlreadySet();
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 {IERC20} from '@openzeppelin-contracts/token/ERC20/IERC20.sol';
import {ILBPair} from './ILBPair.sol';
import {IPendingOwnable} from './IPendingOwnable.sol';
/**
* @title Liquidity Book Factory Interface
* @author Trader Joe
* @notice Required interface of LBFactory contract
*/
interface ILBFactory is IPendingOwnable {
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, uint _binStep);
error LBFactory__LBPairDoesNotExist(IERC20 tokenX, IERC20 tokenY, uint binStep);
error LBFactory__LBPairNotCreated(IERC20 tokenX, IERC20 tokenY, uint binStep);
error LBFactory__FlashLoanFeeAboveMax(uint fees, uint maxFees);
error LBFactory__BinStepTooLow(uint binStep);
error LBFactory__PresetIsLockedForUsers(address user, uint binStep);
error LBFactory__LBPairIgnoredIsAlreadyInTheSameState();
error LBFactory__BinStepHasNoPreset(uint binStep);
error LBFactory__PresetOpenStateIsAlreadyInTheSameState();
error LBFactory__SameFeeRecipient(address feeRecipient);
error LBFactory__SameFlashLoanFee(uint flashLoanFee);
error LBFactory__LBPairSafetyCheckFailed(address LBPairImplementation);
error LBFactory__SameImplementation(address LBPairImplementation);
error LBFactory__ImplementationNotSet();
/**
* @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, uint indexed binStep, ILBPair LBPair, uint pid);
event FeeRecipientSet(address oldRecipient, address newRecipient);
event FlashLoanFeeSet(uint oldFlashLoanFee, uint newFlashLoanFee);
event LBPairImplementationSet(address oldLBPairImplementation, address LBPairImplementation);
event LBPairIgnoredStateChanged(ILBPair indexed LBPair, bool ignored);
event PresetSet(
uint indexed binStep,
uint baseFactor,
uint filterPeriod,
uint decayPeriod,
uint reductionFactor,
uint variableFeeControl,
uint protocolShare,
uint maxVolatilityAccumulator
);
event PresetOpenStateChanged(uint indexed binStep, bool indexed isOpen);
event PresetRemoved(uint indexed binStep);
event QuoteAssetAdded(IERC20 indexed quoteAsset);
event QuoteAssetRemoved(IERC20 indexed quoteAsset);
function getMinBinStep() external pure returns (uint);
function getFeeRecipient() external view returns (address);
function getMaxFlashLoanFee() external pure returns (uint);
function getFlashLoanFee() external view returns (uint);
function getLBPairImplementation() external view returns (address);
function getNumberOfLBPairs() external view returns (uint);
function getLBPairAtIndex(uint id) external returns (ILBPair);
function getNumberOfQuoteAssets() external view returns (uint);
function getQuoteAssetAtIndex(uint index) external view returns (IERC20);
function isQuoteAsset(IERC20 token) external view returns (bool);
function getLBPairInformation(IERC20 tokenX, IERC20 tokenY, uint binStep)
external
view
returns (LBPairInformation memory);
function getPreset(uint binStep)
external
view
returns (
uint baseFactor,
uint filterPeriod,
uint decayPeriod,
uint reductionFactor,
uint variableFeeControl,
uint protocolShare,
uint maxAccumulator,
bool isOpen
);
function getAllBinSteps() external view returns (uint[] memory presetsBinStep);
function getOpenBinSteps() external view returns (uint[] memory openBinStep);
function getAllLBPairs(IERC20 tokenX, IERC20 tokenY)
external
view
returns (LBPairInformation[] memory LBPairsBinStep);
function setLBPairImplementation(address lbPairImplementation) external;
function createLBPair(IERC20 tokenX, IERC20 tokenY, uint24 activeId, uint16 binStep)
external
returns (ILBPair pair);
function setLBPairIgnored(IERC20 tokenX, IERC20 tokenY, uint16 binStep, bool ignored) external;
function setPreset(
uint16 binStep,
uint16 baseFactor,
uint16 filterPeriod,
uint16 decayPeriod,
uint16 reductionFactor,
uint24 variableFeeControl,
uint16 protocolShare,
uint24 maxVolatilityAccumulator,
bool isOpen
) external;
function setPresetOpenState(uint16 binStep, bool isOpen) external;
function removePreset(uint16 binStep) external;
function setFeesParametersOnPair(
IERC20 tokenX,
IERC20 tokenY,
uint16 binStep,
uint16 baseFactor,
uint16 filterPeriod,
uint16 decayPeriod,
uint16 reductionFactor,
uint24 variableFeeControl,
uint16 protocolShare,
uint24 maxVolatilityAccumulator
) external;
function setFeeRecipient(address feeRecipient) external;
function setFlashLoanFee(uint flashLoanFee) external;
function addQuoteAsset(IERC20 quoteAsset) external;
function removeQuoteAsset(IERC20 quoteAsset) external;
function forceDecay(ILBPair lbPair) external;
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import {EnumerableSet} from '@openzeppelin-contracts/utils/structs/EnumerableSet.sol';
/// @title Position Interface
interface IPosManager {
event SetMaxCollCount(uint maxCollCount);
struct PosInfo {
address viewer; // viewer address
uint16 mode; // position mode
}
// NOTE: extra info for hooks (not used in core)
struct PosBorrExtraInfo {
uint128 totalInterest; // total accrued interest since the position is created
uint128 lastDebtAmt; // position's debt amount after the last interaction
}
struct PosCollInfo {
EnumerableSet.AddressSet collTokens; // enumerable set of collateral tokens
mapping(address => uint) collAmts; // collateral token to collateral amts mapping
EnumerableSet.AddressSet wLps; // enumerable set of collateral wlps
mapping(address => EnumerableSet.UintSet) ids; // wlp address to enumerable set of ids mapping
uint8 collCount; // current collateral count (erc20 + wlp)
uint8 wLpCount; // current collateral count (wlp)
}
struct PosBorrInfo {
EnumerableSet.AddressSet pools; // enumerable set of borrow tokens
mapping(address => uint) debtShares; // debt token to debt shares mapping
mapping(address => PosBorrExtraInfo) borrExtraInfos; // debt token to extra info mapping
}
/// @dev get the next nonce of the owner for calculating the next position id
/// @param _owner the position owner
/// @return nextNonce the next nonce of the position owner
function nextNonces(address _owner) external view returns (uint nextNonce);
/// @dev get core address
function core() external view returns (address core);
/// @dev get pending reward token amts for the pos id
/// @param _posId pos id
/// @param _rewardToken reward token
/// @return amt reward token amt
function pendingRewards(uint _posId, address _rewardToken) external view returns (uint amt);
/// @dev get whether the wlp is already collateralized to a position
/// @param _wLp wlp address
/// @param _tokenId wlp token id
/// @return whether the wlp is already collateralized to a position
function isCollateralized(address _wLp, uint _tokenId) external view returns (bool);
/// @dev get the position borrowed info (excluding the extra info)
/// @param _posId position id
/// @return pools the borrowed pool list
/// debtShares the debt shares list of the borrowed pools
function getPosBorrInfo(uint _posId) external view returns (address[] memory pools, uint[] memory debtShares);
/// @dev get the position borrowed extra info
/// @param _posId position id
/// @param _pool borrowed pool address
/// @return totalInterest total accrued interest since the position is created
/// lastDebtAmt position's debt amount after the last interaction
function getPosBorrExtraInfo(uint _posId, address _pool)
external
view
returns (uint totalInterest, uint lastDebtAmt);
/// @dev get the position collateral info
/// @param _posId position id
/// @return pools the collateral pool adddres list
/// amts collateral amts of the collateral pools
/// wLps the collateral wlp list
/// ids the ids of the collateral wlp list
/// wLpAmts the amounts of the collateral wlp list
function getPosCollInfo(uint _posId)
external
view
returns (
address[] memory pools,
uint[] memory amts,
address[] memory wLps,
uint[][] memory ids,
uint[][] memory wLpAmts
);
/// @dev get pool's collateral amount for the position
/// @param _posId position id
/// @param _pool collateral pool address
/// @return amt collateral amount
function getCollAmt(uint _posId, address _pool) external view returns (uint amt);
/// @dev get wrapped lp collateral amount for the position
/// @param _posId position id
/// @param _wLp collateral wlp address
/// @param _tokenId collateral wlp token id
/// @return amt collateral amount
function getCollWLpAmt(uint _posId, address _wLp, uint _tokenId) external view returns (uint amt);
/// @dev get position's collateral count
/// @param _posId position id
/// @return collCount position's collateral count
function getPosCollCount(uint _posId) external view returns (uint8 collCount);
/// @dev get position's wLp count
/// @param _posId position id
function getPosCollWLpCount(uint _posId) external view returns (uint8 wLpCount);
/// @dev get position info
/// @param _posId position id
/// @return viewerAddress position's viewer address
/// mode position's mode
function getPosInfo(uint _posId) external view returns (address viewerAddress, uint16 mode);
/// @dev get position mode
/// @param _posId position id
/// @return mode position's mode
function getPosMode(uint _posId) external view returns (uint16 mode);
/// @dev get pool's debt shares for the position
/// @param _posId position id
/// @param _pool lending pool address
/// @return debtShares debt shares
function getPosDebtShares(uint _posId, address _pool) external view returns (uint debtShares);
/// @dev get pos id at index corresponding to the viewer address (reverse mapping)
/// @param _viewer viewer address
/// @param _index index
/// @return posId pos id
function getViewerPosIdsAt(address _viewer, uint _index) external view returns (uint posId);
/// @dev get pos id length corresponding to the viewer address (reverse mapping)
/// @param _viewer viewer address
/// @return length pos ids length
function getViewerPosIdsLength(address _viewer) external view returns (uint length);
/// @notice only core can call this function
/// @dev update pool's debt share
/// @param _posId position id
/// @param _pool lending pool address
/// @param _debtShares new debt shares
function updatePosDebtShares(uint _posId, address _pool, int _debtShares) external;
/// @notice only core can call this function
/// @dev update position mode
/// @param _posId position id
/// @param _mode new position mode to set to
function updatePosMode(uint _posId, uint16 _mode) external;
/// @notice only core can call this function
/// @dev add lending pool share as collateral to the position
/// @param _posId position id
/// @param _pool lending pool address
/// @return amtIn pool's share collateral amount added to the position
function addCollateral(uint _posId, address _pool) external returns (uint amtIn);
/// @notice only core can call this function
/// @dev add wrapped lp share as collateral to the position
/// @param _posId position id
/// @param _wLp wlp address
/// @param _tokenId wlp token id
/// @return amtIn wlp collateral amount added to the position
function addCollateralWLp(uint _posId, address _wLp, uint _tokenId) external returns (uint amtIn);
/// @notice only core can call this function
/// @dev remove lending pool share from the position
/// @param _posId position id
/// @param _pool lending pool address
/// @param _receiver address to receive the shares
/// @return amtOut pool's share collateral amount removed from the position
function removeCollateralTo(uint _posId, address _pool, uint _shares, address _receiver)
external
returns (uint amtOut);
/// @notice only core can call this function
/// @dev remove wlp from the position
/// @param _posId position id
/// @param _wLp wlp address
/// @param _tokenId wlp token id
/// @param _amt wlp token amount to remove
/// @return amtOut wlp collateral amount removed from the position
function removeCollateralWLpTo(uint _posId, address _wLp, uint _tokenId, uint _amt, address _receiver)
external
returns (uint amtOut);
/// @notice only core can call this function
/// @dev create a new position
/// @param _owner position owner
/// @param _mode position mode
/// @param _viewer position viewer
/// @return posId position id
function createPos(address _owner, uint16 _mode, address _viewer) external returns (uint posId);
/// @dev harvest rewards from the wlp token
/// @param _posId position id
/// @param _wlp wlp address
/// @param _tokenId id of the wlp token
/// @param _to address to receive the rewards
/// @return tokens token address list harvested
/// amts token amt list harvested
function harvestTo(uint _posId, address _wlp, uint _tokenId, address _to)
external
returns (address[] memory tokens, uint[] memory amts);
/// @notice When removing the wrapped LP collateral, the rewards are harvested to the position manager
/// before unwrapping the LP and sending it to the user
/// @dev claim pending reward pending in the position manager
/// @param _posId position id
/// @param _tokens token address list to claim pending reward
/// @param _to address to receive the pending rewards
/// @return amts amount of each reward tokens claimed
function claimPendingRewards(uint _posId, address[] calldata _tokens, address _to)
external
returns (uint[] memory amts);
/// @notice authorized account could be the owner or approved addresses
/// @dev check if the accoount is authorized for the position
/// @param _account account address to check
/// @param _posId position id
/// @return whether the account is authorized to manage the position
function isAuthorized(address _account, uint _posId) external view returns (bool);
/// @notice only guardian can call this function
/// @dev set the max number of the different collateral count (to avoid out-of-gas error)
/// @param _maxCollCount new max collateral count
function setMaxCollCount(uint8 _maxCollCount) external;
/// @notice only position owner can call this function
/// @dev set new position viewer for pos id
/// @param _posId pos id
/// @param _viewer new viewer address
function setPosViewer(uint _posId, address _viewer) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
* @dev Deprecated. This function has issues similar to the ones found in
* {IERC20-approve}, and its usage is discouraged.
*
* Whenever possible, use {safeIncreaseAllowance} and
* {safeDecreaseAllowance} instead.
*/
function safeApprove(IERC20 token, address spender, uint256 value) internal {
// safeApprove should only be called when setting an initial allowance,
// or when resetting it to zero. To increase and decrease it, use
// 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
* Revert on invalid signature.
*/
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)
pragma solidity ^0.8.1;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
*
* Furthermore, `isContract` will also return true if the target contract within
* the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
* which only has an effect at the end of a transaction.
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0
// for contracts in construction, since the code is only stored at the end
// of the constructor execution.
return account.code.length > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
// only check isContract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import {IERC20} from '@openzeppelin-contracts/token/ERC20/IERC20.sol';
import {ILBLegacyPair} from './ILBLegacyPair.sol';
import {IPendingOwnable} from './IPendingOwnable.sol';
/// @title Liquidity Book Factory Interface
/// @author Trader Joe
/// @notice Required interface of LBFactory contract
interface ILBLegacyFactory 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;
ILBLegacyPair LBPair;
bool createdByOwner;
bool ignoredForRouting;
}
event LBPairCreated(
IERC20 indexed tokenX, IERC20 indexed tokenY, uint indexed binStep, ILBLegacyPair LBPair, uint pid
);
event FeeRecipientSet(address oldRecipient, address newRecipient);
event FlashLoanFeeSet(uint oldFlashLoanFee, uint newFlashLoanFee);
event FeeParametersSet(
address indexed sender,
ILBLegacyPair indexed LBPair,
uint binStep,
uint baseFactor,
uint filterPeriod,
uint decayPeriod,
uint reductionFactor,
uint variableFeeControl,
uint protocolShare,
uint maxVolatilityAccumulator
);
event FactoryLockedStatusUpdated(bool unlocked);
event LBPairImplementationSet(address oldLBPairImplementation, address LBPairImplementation);
event LBPairIgnoredStateChanged(ILBLegacyPair indexed LBPair, bool ignored);
event PresetSet(
uint indexed binStep,
uint baseFactor,
uint filterPeriod,
uint decayPeriod,
uint reductionFactor,
uint variableFeeControl,
uint protocolShare,
uint maxVolatilityAccumulator,
uint sampleLifetime
);
event PresetRemoved(uint indexed binStep);
event QuoteAssetAdded(IERC20 indexed quoteAsset);
event QuoteAssetRemoved(IERC20 indexed quoteAsset);
function MAX_FEE() external pure returns (uint);
function MIN_BIN_STEP() external pure returns (uint);
function MAX_BIN_STEP() external pure returns (uint);
function MAX_PROTOCOL_SHARE() external pure returns (uint);
function LBPairImplementation() external view returns (address);
function getNumberOfQuoteAssets() external view returns (uint);
function getQuoteAsset(uint index) external view returns (IERC20);
function isQuoteAsset(IERC20 token) external view returns (bool);
function feeRecipient() external view returns (address);
function flashLoanFee() external view returns (uint);
function creationUnlocked() external view returns (bool);
function allLBPairs(uint id) external returns (ILBLegacyPair);
function getNumberOfLBPairs() external view returns (uint);
function getLBPairInformation(IERC20 tokenX, IERC20 tokenY, uint binStep)
external
view
returns (LBPairInformation memory);
function getPreset(uint16 binStep)
external
view
returns (
uint baseFactor,
uint filterPeriod,
uint decayPeriod,
uint reductionFactor,
uint variableFeeControl,
uint protocolShare,
uint maxAccumulator,
uint sampleLifetime
);
function getAllBinSteps() external view returns (uint[] 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 (ILBLegacyPair pair);
function setLBPairIgnored(IERC20 tokenX, IERC20 tokenY, uint binStep, bool ignored) external;
function setPreset(
uint16 binStep,
uint16 baseFactor,
uint16 filterPeriod,
uint16 decayPeriod,
uint16 reductionFactor,
uint24 variableFeeControl,
uint16 protocolShare,
uint24 maxVolatilityAccumulator,
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 maxVolatilityAccumulator
) external;
function setFeeRecipient(address feeRecipient) external;
function setFlashLoanFee(uint flashLoanFee) external;
function setFactoryLockedState(bool locked) external;
function addQuoteAsset(IERC20 quoteAsset) external;
function removeQuoteAsset(IERC20 quoteAsset) external;
function forceDecay(ILBLegacyPair LBPair) external;
}// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.10;
/// @title Joe V1 Factory Interface
/// @notice Interface to interact with Joe V1 Factory
interface IJoeFactory {
event PairCreated(address indexed token0, address indexed token1, address pair, uint);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function migrator() external view returns (address);
function getPair(address tokenA, address tokenB) external view returns (address pair);
function allPairs(uint) external view returns (address pair);
function allPairsLength() external view returns (uint);
function createPair(address tokenA, address tokenB) external returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
function setMigrator(address) external;
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
/// @title Callback Receiver Interface
interface ICallbackReceiver {
/// @dev handle the callback from core
/// @param _sender the sender address
/// @param _data the data payload to execute on the callback
/// @return result the encoded result of the callback
function coreCallback(address _sender, bytes calldata _data) external payable returns (bytes memory result);
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import '../../receiver/ICallbackReceiver.sol';
interface IERC20LiquidationBot is ICallbackReceiver {
/// @dev flash borrow liquidate a position
/// @param _posId position id to liquidate
/// @param _poolToBorrow pool to flash borrow
/// @param _router router to swap _poolToborrow's underlying to _poolToRepay's underlying
/// @param _poolToRepay pool to repay
/// @param _router2 router to swap _poolToRepay's underlying to _poolOut's underlying
/// @param _poolOut pool to receive liquidated underlying
/// @param _minAmtOut min amount of _poolOut's underlying to receive
function flashLiquidate(
uint _posId,
address _poolToBorrow,
address _router,
address _poolToRepay,
address _router2,
address _poolOut,
uint _minAmtOut
) external;
/// @dev flash borrow liquidate a position and swap to native token
/// @param _posId position id to liquidate
/// @param _poolToBorrow pool to flash borrow
/// @param _router router to swap _poolToborrow's underlying to _poolToRepay's underlying
/// @param _poolToRepay pool to repay
/// @param _router2 router to swap _poolToRepay's underlying to _poolOut's underlying
/// @param _poolOut pool to receive liquidated underlying
/// @param _router3 router to swap _poolOut's underlying to native token
/// @param _minAmtOut min amount of native token to receive
function flashLiquidateReturnNative(
uint _posId,
address _poolToBorrow,
address _router,
address _poolToRepay,
address _router2,
address _poolOut,
address _router3,
uint _minAmtOut
) external;
/// @dev get max amount of underlying to repay a position
/// @param _posId position id to liquidate
/// @param _poolToRepay pool to repay
/// @param _poolOut pool to receive liquidated underlying
/// @return repayToken the token to repay
/// @return maxRepayAmt max amount of underlying to repay
function getMaxRepayAmt(uint _posId, address _poolToRepay, address _poolOut)
external
returns (address repayToken, uint maxRepayAmt);
/// @dev get liquidation info
/// @param _posId position id to liquidate
/// @return bestPoolToRepay pool to repay
/// @return bestPoolOut pool to receive liquidated underlying
/// @return maxRepayAmt max amount of underlying to repay
function getLiquidationInfo(uint _posId)
external
returns (address bestPoolToRepay, address bestPoolOut, uint maxRepayAmt);
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
/// @title Lending Pool Interface
/// @notice rebase token is not supported
interface ILendingPool {
event SetIrm(address _irm);
event SetReserveFactor_e18(uint _reserveFactor_e18);
event SetTreasury(address _treasury);
/// @dev get core address
function core() external view returns (address core);
/// @dev get the interest rate model address
function irm() external view returns (address model);
/// @dev get the reserve factor in 1e18 (1e18 = 100%)
function reserveFactor_e18() external view returns (uint factor_e18);
/// @dev get the pool's underlying token
function underlyingToken() external view returns (address token);
/// @notice total assets = cash + total debts
function totalAssets() external view returns (uint amt);
/// @dev get the pool total debt (underlying token)
function totalDebt() external view returns (uint debt);
/// @dev get the pool total debt shares
function totalDebtShares() external view returns (uint shares);
/// @dev calaculate the debt share from debt amount (without interest accrual)
/// @param _amt the amount of debt
/// @return shares amount of debt shares (rounded up)
function debtAmtToShareStored(uint _amt) external view returns (uint shares);
/// @dev calaculate the debt share from debt amount (with interest accrual)
/// @param _amt the amount of debt
/// @return shares current amount of debt shares (rounded up)
function debtAmtToShareCurrent(uint _amt) external returns (uint shares);
/// @dev calculate the corresponding debt amount from debt share (without interest accrual)
/// @param _shares the amount of debt shares
/// @return amt corresponding debt amount (rounded up)
function debtShareToAmtStored(uint _shares) external view returns (uint amt);
/// @notice this is NOT a view function
/// @dev calculate the corresponding debt amount from debt share (with interest accrual)
/// @param _shares the amount of debt shares
/// @return amt corresponding current debt amount (rounded up)
function debtShareToAmtCurrent(uint _shares) external returns (uint amt);
/// @dev get current supply rate per sec in 1e18
function getSupplyRate_e18() external view returns (uint supplyRate_e18);
/// @dev get current borrow rate per sec in 1e18
function getBorrowRate_e18() external view returns (uint borrowRate_e18);
/// @dev get the pool total cash (underlying token)
function cash() external view returns (uint amt);
/// @dev get the latest timestamp of interest accrual
/// @return lastAccruedTime last accrued time unix timestamp
function lastAccruedTime() external view returns (uint lastAccruedTime);
/// @dev get the treasury address
function treasury() external view returns (address treasury);
/// @notice only core can call this function
/// @dev mint shares to the receiver from the transfered assets
/// @param _receiver address to receive shares
/// @return mintShares amount of shares minted
function mint(address _receiver) external returns (uint mintShares);
/// @notice only core can call this function
/// @dev burn shares and send the underlying assets to the receiver
/// @param _receiver address to receive the underlying tokens
/// @return amt amount of underlying assets transferred
function burn(address _receiver) external returns (uint amt);
/// @notice only core can call this function
/// @dev borrow the asset from the lending pool
/// @param _receiver address to receive the borrowed asset
/// @param _amt amount of asset to borrow
/// @return debtShares debt shares amount recorded from borrowing
function borrow(address _receiver, uint _amt) external returns (uint debtShares);
/// @notice only core can call this function
/// @dev repay the borrowed assets
/// @param _shares the amount of debt shares to repay
/// @return amt assets amount used for repay
function repay(uint _shares) external returns (uint amt);
/// @dev accrue interest from the last accrual
function accrueInterest() external;
/// @dev get the share amounts from underlying asset amt
/// @param _amt the amount of asset to convert to shares
/// @return shares amount of shares (rounded down)
function toShares(uint _amt) external view returns (uint shares);
/// @dev get the asset amount from shares
/// @param _shares the amount of shares to convert to underlying asset amt
/// @return amt amount of underlying asset (rounded down)
function toAmt(uint _shares) external view returns (uint amt);
/// @dev get the share amounts from underlying asset amt (with interest accrual)
/// @param _amt the amount of asset to convert to shares
/// @return shares current amount of shares (rounded down)
function toSharesCurrent(uint _amt) external returns (uint shares);
/// @dev get the asset amount from shares (with interest accrual)
/// @param _shares the amount of shares to convert to underlying asset amt
/// @return amt current amount of underlying asset (rounded down)
function toAmtCurrent(uint _shares) external returns (uint amt);
/// @dev set the interest rate model
/// @param _irm new interest rate model address
function setIrm(address _irm) external;
/// @dev set the pool's reserve factor in 1e18
/// @param _reserveFactor_e18 new reserver factor in 1e18
function setReserveFactor_e18(uint _reserveFactor_e18) external;
/// @dev set the pool's treasury address
/// @param _treasury new treasury address
function setTreasury(address _treasury) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/utils/ERC721Holder.sol)
pragma solidity ^0.8.0;
import "../IERC721Receiver.sol";
/**
* @dev Implementation of the {IERC721Receiver} interface.
*
* Accepts all token transfers.
* Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}.
*/
contract ERC721Holder is IERC721Receiver {
/**
* @dev See {IERC721Receiver-onERC721Received}.
*
* Always returns `IERC721Receiver.onERC721Received.selector`.
*/
function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) {
return this.onERC721Received.selector;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
/**
* @title Liquidity Book Token Interface
* @author Trader Joe
* @notice Interface to interact with the LBToken.
*/
interface ILBToken {
error LBToken__AddressThisOrZero();
error LBToken__InvalidLength();
error LBToken__SelfApproval(address owner);
error LBToken__SpenderNotApproved(address from, address spender);
error LBToken__TransferExceedsBalance(address from, uint id, uint amount);
error LBToken__BurnExceedsBalance(address from, uint id, uint amount);
event TransferBatch(address indexed sender, address indexed from, address indexed to, uint[] ids, uint[] amounts);
event ApprovalForAll(address indexed account, address indexed sender, bool approved);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function totalSupply(uint id) external view returns (uint);
function balanceOf(address account, uint id) external view returns (uint);
function balanceOfBatch(address[] calldata accounts, uint[] calldata ids) external view returns (uint[] memory);
function isApprovedForAll(address owner, address spender) external view returns (bool);
function approveForAll(address spender, bool approved) external;
function batchTransferFrom(address from, address to, uint[] calldata ids, uint[] calldata amounts) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.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
pragma solidity ^0.8.10;
import {IERC20} from '@openzeppelin-contracts/token/ERC20/IERC20.sol';
/// @title Liquidity Book Flashloan Callback Interface
/// @author Trader Joe
/// @notice Required interface to interact with LB flash loans
interface ILBFlashLoanCallback {
function LBFlashLoanCallback(
address sender,
IERC20 tokenX,
IERC20 tokenY,
bytes32 amounts,
bytes32 totalFees,
bytes calldata data
) external returns (bytes32);
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
import {ILBRouter} from '../../common/moe_v2/ILBRouter.sol';
struct ExactInputParams {
bytes path;
address recipient;
uint deadline;
uint amountIn;
uint amountOutMinimum;
}
struct ExactOutputParams {
bytes path;
address recipient;
uint deadline;
uint amountOut;
uint amountInMaximum;
}
interface ISwapRouter {
// ====================== uniswap v2 =====================
function swapExactTokensForTokens(
uint amountIn,
uint amountOutMin,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
function swapTokensForExactTokens(
uint amountOut,
uint amountInMax,
address[] calldata path,
address to,
uint deadline
) external returns (uint[] memory amounts);
// ====================== uniswap v3 =====================
function exactInput(ExactInputParams memory params) external payable returns (uint amountOut);
function exactOutput(ExactOutputParams calldata params) external payable returns (uint amountIn);
}
enum SwapOperation {
EXACT_IN,
EXACT_OUT
}
struct UniswapV2SwapInfo {
address[] path;
}
struct UniswapV3SwapInfo {
// encode of [token0, fee, token1, fee, token2, ...]
bytes path;
}
struct JoeV2_1SwapInfo {
ILBRouter.Path path;
}
interface ISwapEncoder {
function getCalldata(
address _swapper,
bytes memory _swapInfo,
SwapOperation _operation,
uint _routerType,
uint _amount
) external view returns (bytes memory);
}// SPDX-License-Identifier: None
pragma solidity ^0.8.19;
/// @title Multicall Interface
interface IMulticall {
/// @dev Perform multiple calls according to the provided _data. Reverts with reason if any of the calls failed.
/// @notice `msg.value` should not be trusted or used in the multicall data.
/// @param _data The encoded function data for each subcall.
/// @return results The call results, if success.
function multicall(bytes[] calldata _data) external payable returns (bytes[] memory results);
}{
"evmVersion": "paris",
"libraries": {},
"metadata": {
"appendCBOR": true,
"bytecodeHash": "ipfs",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"@forge-std/=lib/forge-std/src/",
"@openzeppelin-contracts/=contracts/.cache/OpenZeppelin/v4.9.3/",
"@openzeppelin-contracts-upgradeable/=contracts/.cache/OpenZeppelin-Upgradeable/v4.9.3/",
"ds-test/=lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/"
],
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_core","type":"address"},{"internalType":"address","name":"_posManager","type":"address"},{"internalType":"address","name":"_registry","type":"address"},{"internalType":"address","name":"_lens","type":"address"},{"internalType":"address","name":"_wNative","type":"address"},{"internalType":"uint256","name":"_bufferBPS","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"coreCallback","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_posId","type":"uint256"},{"internalType":"address","name":"_poolToBorrow","type":"address"},{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_poolToRepay","type":"address"},{"internalType":"address","name":"_router2","type":"address"},{"internalType":"address","name":"_poolOut","type":"address"},{"internalType":"uint256","name":"_minAmtOut","type":"uint256"}],"name":"flashLiquidate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_posId","type":"uint256"},{"internalType":"address","name":"_poolToBorrow","type":"address"},{"internalType":"address","name":"_router","type":"address"},{"internalType":"address","name":"_poolToRepay","type":"address"},{"internalType":"address","name":"_router2","type":"address"},{"internalType":"address","name":"_poolOut","type":"address"},{"internalType":"address","name":"_router3","type":"address"},{"internalType":"uint256","name":"_minAmtOut","type":"uint256"}],"name":"flashLiquidateReturnNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_posId","type":"uint256"}],"name":"getLiquidationInfo","outputs":[{"internalType":"address","name":"bestPoolToRepay","type":"address"},{"internalType":"address","name":"bestPoolOut","type":"address"},{"internalType":"uint256","name":"maxRepayAmt","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_posId","type":"uint256"},{"internalType":"address","name":"_poolToRepay","type":"address"},{"internalType":"address","name":"_poolOut","type":"address"}],"name":"getMaxRepayAmt","outputs":[{"internalType":"address","name":"repayToken","type":"address"},{"internalType":"uint256","name":"maxRepayAmt","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
6101806040523480156200001257600080fd5b5060405162003930380380620039308339810160408190526200003591620001cf565b6001600160a01b03808716608081905286821660a05290851660e052604080516307dc0d1d60e41b81529051637dc0d1d0916004808201926020929091908290030181865afa1580156200008d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b3919062000247565b6001600160a01b03908116610100528381166101205282811661014052604051630bed2fd960e21b81526001600482015230602482015290871690632fb4bf64906044016020604051808303816000875af115801562000117573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200013d91906200026c565b60c052612710811115620001a25760405162461bcd60e51b815260206004820152602260248201527f4c69717569646174696f6e426f743a20494e56414c49445f4255464645525f42604482015261505360f01b606482015260840160405180910390fd5b6101605250620002869350505050565b80516001600160a01b0381168114620001ca57600080fd5b919050565b60008060008060008060c08789031215620001e957600080fd5b620001f487620001b2565b95506200020460208801620001b2565b94506200021460408801620001b2565b93506200022460608801620001b2565b92506200023460808801620001b2565b915060a087015190509295509295509295565b6000602082840312156200025a57600080fd5b6200026582620001b2565b9392505050565b6000602082840312156200027f57600080fd5b5051919050565b60805160a05160c05160e051610100516101205161014051610160516135aa620003866000396000611d5e015260008181610202015281816102780152818161044a01526104d60152600061124f01526000818161090a015261207d0152600081816102470152610e07015260008181610a3e0152818161107f015281816113860152818161156d015261163601526000818161074b0152818161080201528181610d1801528181611ae7015281816121d90152612323015260008181610b060152818161113801528181611344015281816116ce015281816118a301528181611947015281816119d801528181611b58015261269301526135aa6000f3fe6080604052600436106100595760003560e01c806314f7ee2614610065578063150b7a0214610087578063304c9e6e146100c557806350ef5c35146100e557806353d908161461012b5780638a839fde1461016a57600080fd5b3661006057005b600080fd5b34801561007157600080fd5b50610085610080366004612a79565b61018a565b005b34801561009357600080fd5b506100a76100a2366004612b7d565b610611565b6040516001600160e01b031990911681526020015b60405180910390f35b3480156100d157600080fd5b506100856100e0366004612c2b565b610622565b3480156100f157600080fd5b50610105610100366004612caf565b610743565b604080516001600160a01b039485168152939092166020840152908201526060016100bc565b34801561013757600080fd5b5061014b610146366004612cc8565b610a00565b604080516001600160a01b0390931683526020830191909152016100bc565b61017d610178366004612d0a565b610a1c565b6040516100bc9190612dde565b61019888888888888861107d565b6000836001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190612df1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316826001600160a01b031614610432576102438285611756565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632233942330857f000000000000000000000000000000000000000000000000000000000000000060008a896001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016102d591906001600160a01b0391909116815260200190565b602060405180830381865afa1580156102f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103169190612e0e565b6040518763ffffffff1660e01b815260040161033796959493929190612e27565b600060405180830381865afa158015610354573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261037c9190810190612ecc565b9050846001600160a01b0316816040516103969190612f00565b6000604051808303816000865af19150503d80600081146103d3576040519150601f19603f3d011682016040523d82523d6000602084013e6103d8565b606091505b505080925050816104305760405162461bcd60e51b815260206004820152601b60248201527f4c69717569646174696f6e426f743a20535741505f4641494c4544000000000060448201526064015b60405180910390fd5b505b6040516370a0823160e01b81523060048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906370a0823190602401602060405180830381865afa158015610499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104bd9190612e0e565b604051632e1a7d4d60e01b8152600481018290529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561052257600080fd5b505af1158015610536573d6000803e3d6000fd5b505050504790508381101561055d5760405162461bcd60e51b815260040161042790612f1c565b60405133908290600081818185875af1925050503d806000811461059d576040519150601f19603f3d011682016040523d82523d6000602084013e6105a2565b606091505b505080925050816106045760405162461bcd60e51b815260206004820152602660248201527f4c69717569646174696f6e426f743a204e41544956455f5452414e534645525f60448201526511905253115160d21b6064820152608401610427565b5050505050505050505050565b630a85bd0160e11b5b949350505050565b61063087878787878761107d565b6000826001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015610670573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106949190612df1565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156106de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107029190612e0e565b9050828110156107245760405162461bcd60e51b815260040161042790612f1c565b6107386001600160a01b0383163383611847565b505050505050505050565b6000806000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663056b0ac7866040518263ffffffff1660e01b815260040161079791815260200190565b600060405180830381865afa1580156107b4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107dc91908101906130d2565b505060405163947557b360e01b8152600481018990529293506000926001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016925063947557b39150602401600060405180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261087391908101906131a3565b5090506000805b83518110156109f55760005b83518110156109ec5760008060006108d18c8886815181106108aa576108aa613206565b60200260200101518a88815181106108c4576108c4613206565b6020026020010151611899565b93505092509250816000036108e8575050506109e4565b6040516339fa57cb60e11b81526001600160a01b0384811660048301526000917f0000000000000000000000000000000000000000000000000000000000000000909116906373f4af9690602401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109779190612e0e565b6109819084613232565b905060006109988284670de0b6b3a76400006124be565b9050878111156109de57839a508886815181106109b7576109b7613206565b60200260200101519c508987815181106109d3576109d3613206565b60200260200101519b505b50505050505b600101610886565b5060010161087a565b505050509193909250565b600080610a0e858585611899565b509197909650945050505050565b6060600080808080610a3087890189613249565b9450945094509450945060007f00000000000000000000000000000000000000000000000000000000000000008303610b75576040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa158015610aa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acb9190612e0e565b9050610ae16001600160a01b0386168683611847565b604051637fe6bc3d60e01b81526001600160a01b0386811660048301523060248301527f00000000000000000000000000000000000000000000000000000000000000001690637fe6bc3d906044016020604051808303816000875af1158015610b4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b739190612e0e565b505b6000856001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd99190612df1565b90506000856001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f9190612df1565b6040516370a0823160e01b81523060048201529091506001600160a01b038316906370a0823190602401602060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610caa9190612e0e565b9250806001600160a01b0316826001600160a01b031603610cef5760408051602081018590520160405160208183030381529060405298505050505050505050611076565b6040516310e28e7160e01b8152600481018690526001600160a01b0387811660248301526000917f0000000000000000000000000000000000000000000000000000000000000000909116906310e28e7190604401602060405180830381865afa158015610d61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d859190612e0e565b9050610d9185826125a8565b6040516318ddac3960e11b815260048101829052909550600091506001600160a01b038816906331bb587290602401602060405180830381865afa158015610ddd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e019190612e0e565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316632233942330868660018f896001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610e7591906001600160a01b0391909116815260200190565b602060405180830381865afa158015610e92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb69190612e0e565b610ec0908a6132a4565b6040518763ffffffff1660e01b8152600401610ee196959493929190612e27565b600060405180830381865afa158015610efe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f269190810190612ecc565b9050610f32848b611756565b60008a6001600160a01b031682604051610f4c9190612f00565b6000604051808303816000865af19150503d8060008114610f89576040519150601f19603f3d011682016040523d82523d6000602084013e610f8e565b606091505b5050905080610fdf5760405162461bcd60e51b815260206004820152601b60248201527f4c69717569646174696f6e426f743a20535741505f4641494c454400000000006044820152606401610427565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015611023573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110479190612e0e565b60405160200161105991815260200190565b6040516020818303038152906040529b5050505050505050505050505b9392505050565b7f000000000000000000000000000000000000000000000000000000000000000086036110ec5760405162461bcd60e51b815260206004820152601e60248201527f4c69717569646174696f6e426f743a20494e56414c49445f504f535f494400006044820152606401610427565b6000806110fa888685611899565b5060408051600580825260c082019092529395509093506000929150816020015b606081526020019060019003908161111b57905050905061115c837f0000000000000000000000000000000000000000000000000000000000000000611756565b6040516331a86fe160e01b8152600481018390526000906001600160a01b038a16906331a86fe1906024016020604051808303816000875af11580156111a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ca9190612e0e565b9050846001600160a01b0316896001600160a01b031603611210576127106111f38a89846125c2565b6111ff90612af8613232565b61120991906132cd565b90506112bf565b866001600160a01b0316896001600160a01b0316146112bf57604051634761bfb760e01b8152600160048201526001600160a01b038a811660248301527f00000000000000000000000000000000000000000000000000000000000000001690634761bfb7906044016020604051808303816000875af1158015611298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bc9190612e0e565b90505b866001600160a01b0316896001600160a01b03161461136a576000896001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015611318573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133c9190612df1565b9050611368817f0000000000000000000000000000000000000000000000000000000000000000611756565b505b604080516001600160a01b038b166024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006064820152306084808301919091528251808303909101815260a49091019091526020810180516001600160e01b03166308ba54eb60e21b179052825183906000906113f3576113f3613206565b602090810291909101810191909152604080516001600160a01b038b8116938201939093528b8316818301529189166060830152608082018c905260a08083018690528151808403909101815260c08301909152633eb0617f60e11b925061146291309160009160e4016132ef565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050816001815181106114a8576114a8613206565b6020908102919091010152604051602481018a90526001600160a01b0380881660448301526064820184905285166084820152600060a4820152635a1b8ac160e01b9060c401604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050508160028151811061153457611534613206565b602090810291909101810191909152604080516001600160a01b03808916938201939093528287169181019190915290891660608201527f0000000000000000000000000000000000000000000000000000000000000000608082015260001960a0820152633eb0617f60e11b90309060009060c00160408051601f19818403018152908290526115c99392916024016132ef565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050508160038151811061160f5761160f613206565b60209081029190910101526040516001600160a01b038916602482015260001960448201527f00000000000000000000000000000000000000000000000000000000000000006064820152638cd2e0c760e01b90608401604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050816004815181106116ac576116ac613206565b6020908102919091010152604051631592ca1b60e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063ac9650d890611703908490600401613325565b6000604051808303816000875af1158015611722573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261174a9190810190613387565b50505050505050505050565b604051636eb1769f60e11b81523060048201526001600160a01b03828116602483015283169063dd62ed3e90604401602060405180830381865afa1580156117a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c69190612e0e565b6000036118435760405163095ea7b360e01b81526001600160a01b038281166004830152600019602483015283169063095ea7b3906044016020604051808303816000875af115801561181d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118419190613437565b505b5050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611841908490612869565b60008060008060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166379502c556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119239190612df1565b60405163b26ec9af60e01b8152600481018a90529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063b26ec9af906024016020604051808303816000875af1158015611990573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b49190612e0e565b60405163051ff3a360e21b8152600481018b90529091506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063147fce8c906024016020604051808303816000875af1158015611a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a459190612e0e565b9050808210611a615750600094508493508392506124b5915050565b886001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac39190612df1565b604051633e4b135360e21b8152600481018c90529097506000906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f92c4d4c90602401602060405180830381865afa158015611b2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b529190613459565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a6d35d796040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd89190612df1565b90506001600160a01b03811663b4fc94948385611bfd670de0b6b3a764000089613232565b611c0791906132cd565b8c8e6001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6a9190612df1565b6040516001600160e01b031960e087901b16815261ffff909416600485015260248401929092526001600160a01b039081166044840152166064820152608401602060405180830381865afa158015611cc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ceb9190612e0e565b95505084600003611d3e5760405162461bcd60e51b815260206004820181905260248201527f4c69717569646174696f6e426f743a20504f534954494f4e5f4845414c5448596044820152606401610427565b6040516369fc8a8560e01b815261ffff82166004820152600090612710907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b038816906369fc8a8590602401602060405180830381865afa158015611daf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd39190612e0e565b611ddd9190613232565b611de791906132cd565b60405163fea1a64f60e01b815261ffff841660048201526001600160a01b038c8116602483015291925060009187169063fea1a64f906044016040805180830381865afa158015611e3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e609190613499565b60405163fea1a64f60e01b815261ffff851660048201526001600160a01b038e8116602483015291925060009188169063fea1a64f906044016040805180830381865afa158015611eb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed99190613499565b90506000611eef670de0b6b3a764000088613232565b611ef98786613232565b611f0391906132a4565b9050600082602001516001600160801b031685611f209190613232565b8451909150611f39908b906001600160801b0316613232565b611f4390826132a4565b9050611f5882670de0b6b3a7640000836124be565b9b505050505050505050600080600060026001600160401b03811115611f8057611f80612b10565b604051908082528060200260200182016040528015611fa9578160200160208202803683370190505b5090508781600081518110611fc057611fc0613206565b60200260200101906001600160a01b031690816001600160a01b031681525050886001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa15801561201e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120429190612df1565b8160018151811061205557612055613206565b6001600160a01b0392831660209182029290920101526040516308f114af60e21b81526000917f000000000000000000000000000000000000000000000000000000000000000016906323c452bc906120b29085906004016134f3565b600060405180830381865afa1580156120cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526120f79190810190613540565b90508060008151811061210c5761210c613206565b602002602001015193508060018151811061212957612129613206565b602002602001015192505050818661214191906132cd565b6040516333bc0c1160e21b8152600481018290529096506001600160a01b038a169063cef0304490602401602060405180830381865afa158015612189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ad9190612e0e565b6040516310e28e7160e01b8152600481018c90526001600160a01b038b811660248301529196506000917f000000000000000000000000000000000000000000000000000000000000000016906310e28e7190604401602060405180830381865afa158015612220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122449190612e0e565b905061225086826125a8565b6040516318ddac3960e11b8152600481018290529096506001600160a01b038b1691506331bb587290602401602060405180830381865afa158015612299573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122bd9190612e0e565b95506000670de0b6b3a76400006122d48689613232565b6122de91906132cd565b90506000826122ed8584613232565b6122f791906132cd565b60405163402414b360e01b8152600481018e90526001600160a01b038c811660248301529192506000917f0000000000000000000000000000000000000000000000000000000000000000169063402414b390604401602060405180830381865afa15801561236a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238e9190612e0e565b604051630c1e134760e11b8152600481018290529091506000906001600160a01b038d169063183c268e90602401602060405180830381865afa1580156123d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fd9190612e0e565b9050828110156124ad576000866124148784613232565b61241e91906132cd565b905088612433670de0b6b3a764000083613232565b61243d91906132cd565b6040516333bc0c1160e21b815260048101829052909b506001600160a01b038f169063cef0304490602401602060405180830381865afa158015612485573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a99190612e0e565b9950505b505050505050505b93509350935093565b60008080600019858709858702925082811083820303915050806000036124f8578382816124ee576124ee6132b7565b0492505050611076565b80841161253f5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b6044820152606401610427565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b60008183106125b757816125b9565b825b90505b92915050565b600080846001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015612603573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126279190612df1565b90506000846001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015612669573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268d9190612df1565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127139190612df1565b6040805160028082526060820183529293506000929091602083019080368337019050509050838160008151811061274d5761274d613206565b60200260200101906001600160a01b031690816001600160a01b031681525050828160018151811061278157612781613206565b6001600160a01b0392831660209182029290920101526040516308f114af60e21b81526000918416906323c452bc906127be9085906004016134f3565b600060405180830381865afa1580156127db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526128039190810190613540565b905060008160008151811061281a5761281a613206565b6020026020010151905060008260018151811061283957612839613206565b6020026020010151905081818a6128509190613232565b61285a91906132cd565b9b9a5050505050505050505050565b60006128be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661293e9092919063ffffffff16565b90508051600014806128df5750808060200190518101906128df9190613437565b6118415760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610427565b606061061a848460008585600080866001600160a01b031685876040516129659190612f00565b60006040518083038185875af1925050503d80600081146129a2576040519150601f19603f3d011682016040523d82523d6000602084013e6129a7565b606091505b50915091506129b8878383876129c3565b979650505050505050565b60608315612a32578251600003612a2b576001600160a01b0385163b612a2b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610427565b508161061a565b61061a8383815115612a475781518083602001fd5b8060405162461bcd60e51b81526004016104279190612dde565b6001600160a01b0381168114612a7657600080fd5b50565b600080600080600080600080610100898b031215612a9657600080fd5b883597506020890135612aa881612a61565b96506040890135612ab881612a61565b95506060890135612ac881612a61565b94506080890135612ad881612a61565b935060a0890135612ae881612a61565b925060c0890135612af881612a61565b8092505060e089013590509295985092959890939650565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715612b4e57612b4e612b10565b604052919050565b60006001600160401b03821115612b6f57612b6f612b10565b50601f01601f191660200190565b60008060008060808587031215612b9357600080fd5b8435612b9e81612a61565b93506020850135612bae81612a61565b92506040850135915060608501356001600160401b03811115612bd057600080fd5b8501601f81018713612be157600080fd5b8035612bf4612bef82612b56565b612b26565b818152886020838501011115612c0957600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080600080600080600060e0888a031215612c4657600080fd5b873596506020880135612c5881612a61565b95506040880135612c6881612a61565b94506060880135612c7881612a61565b93506080880135612c8881612a61565b925060a0880135612c9881612a61565b8092505060c0880135905092959891949750929550565b600060208284031215612cc157600080fd5b5035919050565b600080600060608486031215612cdd57600080fd5b833592506020840135612cef81612a61565b91506040840135612cff81612a61565b809150509250925092565b600080600060408486031215612d1f57600080fd5b8335612d2a81612a61565b925060208401356001600160401b0380821115612d4657600080fd5b818601915086601f830112612d5a57600080fd5b813581811115612d6957600080fd5b876020828501011115612d7b57600080fd5b6020830194508093505050509250925092565b60005b83811015612da9578181015183820152602001612d91565b50506000910152565b60008151808452612dca816020860160208601612d8e565b601f01601f19169290920160200192915050565b6020815260006125b96020830184612db2565b600060208284031215612e0357600080fd5b815161107681612a61565b600060208284031215612e2057600080fd5b5051919050565b6001600160a01b0387811682528681166020830152858116604083015260c082019060028610612e6757634e487b7160e01b600052602160045260246000fd5b8560608401528085166080840152508260a0830152979650505050505050565b600082601f830112612e9857600080fd5b8151612ea6612bef82612b56565b818152846020838601011115612ebb57600080fd5b61061a826020830160208701612d8e565b600060208284031215612ede57600080fd5b81516001600160401b03811115612ef457600080fd5b61061a84828501612e87565b60008251612f12818460208701612d8e565b9190910192915050565b6020808252602a908201527f4c69717569646174696f6e426f743a20494e53554646494349454e545f4f555460408201526914155517d05353d5539560b21b606082015260800190565b60006001600160401b03821115612f7f57612f7f612b10565b5060051b60200190565b600082601f830112612f9a57600080fd5b81516020612faa612bef83612f66565b82815260059290921b84018101918181019086841115612fc957600080fd5b8286015b84811015612fed578051612fe081612a61565b8352918301918301612fcd565b509695505050505050565b600082601f83011261300957600080fd5b81516020613019612bef83612f66565b82815260059290921b8401810191818101908684111561303857600080fd5b8286015b84811015612fed578051835291830191830161303c565b600082601f83011261306457600080fd5b81516020613074612bef83612f66565b82815260059290921b8401810191818101908684111561309357600080fd5b8286015b84811015612fed5780516001600160401b038111156130b65760008081fd5b6130c48986838b0101612ff8565b845250918301918301613097565b600080600080600060a086880312156130ea57600080fd5b85516001600160401b038082111561310157600080fd5b61310d89838a01612f89565b9650602088015191508082111561312357600080fd5b61312f89838a01612ff8565b9550604088015191508082111561314557600080fd5b61315189838a01612f89565b9450606088015191508082111561316757600080fd5b61317389838a01613053565b9350608088015191508082111561318957600080fd5b5061319688828901613053565b9150509295509295909350565b600080604083850312156131b657600080fd5b82516001600160401b03808211156131cd57600080fd5b6131d986838701612f89565b935060208501519150808211156131ef57600080fd5b506131fc85828601612ff8565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176125bc576125bc61321c565b600080600080600060a0868803121561326157600080fd5b853561326c81612a61565b9450602086013561327c81612a61565b9350604086013561328c81612a61565b94979396509394606081013594506080013592915050565b818103818111156125bc576125bc61321c565b634e487b7160e01b600052601260045260246000fd5b6000826132ea57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b038416815260ff8316602082015260606040820181905260009061331c90830184612db2565b95945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561337a57603f19888603018452613368858351612db2565b9450928501929085019060010161334c565b5092979650505050505050565b6000602080838503121561339a57600080fd5b82516001600160401b03808211156133b157600080fd5b818501915085601f8301126133c557600080fd5b81516133d3612bef82612f66565b81815260059190911b830184019084810190888311156133f257600080fd5b8585015b8381101561342a5780518581111561340e5760008081fd5b61341c8b89838a0101612e87565b8452509186019186016133f6565b5098975050505050505050565b60006020828403121561344957600080fd5b8151801515811461107657600080fd5b60006020828403121561346b57600080fd5b815161ffff8116811461107657600080fd5b80516001600160801b038116811461349457600080fd5b919050565b6000604082840312156134ab57600080fd5b604051604081018181106001600160401b03821117156134cd576134cd612b10565b6040526134d98361347d565b81526134e76020840161347d565b60208201529392505050565b6020808252825182820181905260009190848201906040850190845b818110156135345783516001600160a01b03168352928401929184019160010161350f565b50909695505050505050565b60006020828403121561355257600080fd5b81516001600160401b0381111561356857600080fd5b61061a84828501612ff856fea2646970667358221220cd826fe5b0dd4057a1ee0346428aee674996c290beb7089a6aabf80e7b1d688d64736f6c63430008130033000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc50000000000000000000000000e7401707cd08c03cdb53daef3295ddfb68bba9200000000000000000000000094670598e98f8dad95d85932dd85cbd050ce14020000000000000000000000004403f4296bef042a08785077d67f4700478800c500000000000000000000000078c1b0c915c4faa5fffa6cabf0219da63d7f4cb8000000000000000000000000000000000000000000000000000000000000270f
Deployed Bytecode
0x6080604052600436106100595760003560e01c806314f7ee2614610065578063150b7a0214610087578063304c9e6e146100c557806350ef5c35146100e557806353d908161461012b5780638a839fde1461016a57600080fd5b3661006057005b600080fd5b34801561007157600080fd5b50610085610080366004612a79565b61018a565b005b34801561009357600080fd5b506100a76100a2366004612b7d565b610611565b6040516001600160e01b031990911681526020015b60405180910390f35b3480156100d157600080fd5b506100856100e0366004612c2b565b610622565b3480156100f157600080fd5b50610105610100366004612caf565b610743565b604080516001600160a01b039485168152939092166020840152908201526060016100bc565b34801561013757600080fd5b5061014b610146366004612cc8565b610a00565b604080516001600160a01b0390931683526020830191909152016100bc565b61017d610178366004612d0a565b610a1c565b6040516100bc9190612dde565b61019888888888888861107d565b6000836001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa1580156101d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101fc9190612df1565b905060007f00000000000000000000000078c1b0c915c4faa5fffa6cabf0219da63d7f4cb86001600160a01b0316826001600160a01b031614610432576102438285611756565b60007f00000000000000000000000094670598e98f8dad95d85932dd85cbd050ce14026001600160a01b0316632233942330857f00000000000000000000000078c1b0c915c4faa5fffa6cabf0219da63d7f4cb860008a896001600160a01b03166370a08231306040518263ffffffff1660e01b81526004016102d591906001600160a01b0391909116815260200190565b602060405180830381865afa1580156102f2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103169190612e0e565b6040518763ffffffff1660e01b815260040161033796959493929190612e27565b600060405180830381865afa158015610354573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261037c9190810190612ecc565b9050846001600160a01b0316816040516103969190612f00565b6000604051808303816000865af19150503d80600081146103d3576040519150601f19603f3d011682016040523d82523d6000602084013e6103d8565b606091505b505080925050816104305760405162461bcd60e51b815260206004820152601b60248201527f4c69717569646174696f6e426f743a20535741505f4641494c4544000000000060448201526064015b60405180910390fd5b505b6040516370a0823160e01b81523060048201526000907f00000000000000000000000078c1b0c915c4faa5fffa6cabf0219da63d7f4cb86001600160a01b0316906370a0823190602401602060405180830381865afa158015610499573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104bd9190612e0e565b604051632e1a7d4d60e01b8152600481018290529091507f00000000000000000000000078c1b0c915c4faa5fffa6cabf0219da63d7f4cb86001600160a01b031690632e1a7d4d90602401600060405180830381600087803b15801561052257600080fd5b505af1158015610536573d6000803e3d6000fd5b505050504790508381101561055d5760405162461bcd60e51b815260040161042790612f1c565b60405133908290600081818185875af1925050503d806000811461059d576040519150601f19603f3d011682016040523d82523d6000602084013e6105a2565b606091505b505080925050816106045760405162461bcd60e51b815260206004820152602660248201527f4c69717569646174696f6e426f743a204e41544956455f5452414e534645525f60448201526511905253115160d21b6064820152608401610427565b5050505050505050505050565b630a85bd0160e11b5b949350505050565b61063087878787878761107d565b6000826001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015610670573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106949190612df1565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038316906370a0823190602401602060405180830381865afa1580156106de573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107029190612e0e565b9050828110156107245760405162461bcd60e51b815260040161042790612f1c565b6107386001600160a01b0383163383611847565b505050505050505050565b6000806000807f0000000000000000000000000e7401707cd08c03cdb53daef3295ddfb68bba926001600160a01b031663056b0ac7866040518263ffffffff1660e01b815260040161079791815260200190565b600060405180830381865afa1580156107b4573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107dc91908101906130d2565b505060405163947557b360e01b8152600481018990529293506000926001600160a01b037f0000000000000000000000000e7401707cd08c03cdb53daef3295ddfb68bba9216925063947557b39150602401600060405180830381865afa15801561084b573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261087391908101906131a3565b5090506000805b83518110156109f55760005b83518110156109ec5760008060006108d18c8886815181106108aa576108aa613206565b60200260200101518a88815181106108c4576108c4613206565b6020026020010151611899565b93505092509250816000036108e8575050506109e4565b6040516339fa57cb60e11b81526001600160a01b0384811660048301526000917f0000000000000000000000004e195a32b2f6eba9c4565ba49bef34f23c2c0350909116906373f4af9690602401602060405180830381865afa158015610953573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109779190612e0e565b6109819084613232565b905060006109988284670de0b6b3a76400006124be565b9050878111156109de57839a508886815181106109b7576109b7613206565b60200260200101519c508987815181106109d3576109d3613206565b60200260200101519b505b50505050505b600101610886565b5060010161087a565b505050509193909250565b600080610a0e858585611899565b509197909650945050505050565b6060600080808080610a3087890189613249565b9450945094509450945060007f328046a1d3c347f7c3d899996e157a00e5dea81e212c70683d5e4e3f7356ef208303610b75576040516370a0823160e01b81523060048201526001600160a01b038616906370a0823190602401602060405180830381865afa158015610aa7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610acb9190612e0e565b9050610ae16001600160a01b0386168683611847565b604051637fe6bc3d60e01b81526001600160a01b0386811660048301523060248301527f000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc51690637fe6bc3d906044016020604051808303816000875af1158015610b4f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b739190612e0e565b505b6000856001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015610bb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd99190612df1565b90506000856001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c1b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c3f9190612df1565b6040516370a0823160e01b81523060048201529091506001600160a01b038316906370a0823190602401602060405180830381865afa158015610c86573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610caa9190612e0e565b9250806001600160a01b0316826001600160a01b031603610cef5760408051602081018590520160405160208183030381529060405298505050505050505050611076565b6040516310e28e7160e01b8152600481018690526001600160a01b0387811660248301526000917f0000000000000000000000000e7401707cd08c03cdb53daef3295ddfb68bba92909116906310e28e7190604401602060405180830381865afa158015610d61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d859190612e0e565b9050610d9185826125a8565b6040516318ddac3960e11b815260048101829052909550600091506001600160a01b038816906331bb587290602401602060405180830381865afa158015610ddd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e019190612e0e565b905060007f00000000000000000000000094670598e98f8dad95d85932dd85cbd050ce14026001600160a01b0316632233942330868660018f896001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401610e7591906001600160a01b0391909116815260200190565b602060405180830381865afa158015610e92573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eb69190612e0e565b610ec0908a6132a4565b6040518763ffffffff1660e01b8152600401610ee196959493929190612e27565b600060405180830381865afa158015610efe573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610f269190810190612ecc565b9050610f32848b611756565b60008a6001600160a01b031682604051610f4c9190612f00565b6000604051808303816000865af19150503d8060008114610f89576040519150601f19603f3d011682016040523d82523d6000602084013e610f8e565b606091505b5050905080610fdf5760405162461bcd60e51b815260206004820152601b60248201527f4c69717569646174696f6e426f743a20535741505f4641494c454400000000006044820152606401610427565b6040516370a0823160e01b81523060048201526001600160a01b038516906370a0823190602401602060405180830381865afa158015611023573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110479190612e0e565b60405160200161105991815260200190565b6040516020818303038152906040529b5050505050505050505050505b9392505050565b7f328046a1d3c347f7c3d899996e157a00e5dea81e212c70683d5e4e3f7356ef2086036110ec5760405162461bcd60e51b815260206004820152601e60248201527f4c69717569646174696f6e426f743a20494e56414c49445f504f535f494400006044820152606401610427565b6000806110fa888685611899565b5060408051600580825260c082019092529395509093506000929150816020015b606081526020019060019003908161111b57905050905061115c837f000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc5611756565b6040516331a86fe160e01b8152600481018390526000906001600160a01b038a16906331a86fe1906024016020604051808303816000875af11580156111a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ca9190612e0e565b9050846001600160a01b0316896001600160a01b031603611210576127106111f38a89846125c2565b6111ff90612af8613232565b61120991906132cd565b90506112bf565b866001600160a01b0316896001600160a01b0316146112bf57604051634761bfb760e01b8152600160048201526001600160a01b038a811660248301527f0000000000000000000000004403f4296bef042a08785077d67f4700478800c51690634761bfb7906044016020604051808303816000875af1158015611298573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112bc9190612e0e565b90505b866001600160a01b0316896001600160a01b03161461136a576000896001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015611318573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061133c9190612df1565b9050611368817f000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc5611756565b505b604080516001600160a01b038b166024820152604481018390527f328046a1d3c347f7c3d899996e157a00e5dea81e212c70683d5e4e3f7356ef206064820152306084808301919091528251808303909101815260a49091019091526020810180516001600160e01b03166308ba54eb60e21b179052825183906000906113f3576113f3613206565b602090810291909101810191909152604080516001600160a01b038b8116938201939093528b8316818301529189166060830152608082018c905260a08083018690528151808403909101815260c08301909152633eb0617f60e11b925061146291309160009160e4016132ef565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050816001815181106114a8576114a8613206565b6020908102919091010152604051602481018a90526001600160a01b0380881660448301526064820184905285166084820152600060a4820152635a1b8ac160e01b9060c401604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050508160028151811061153457611534613206565b602090810291909101810191909152604080516001600160a01b03808916938201939093528287169181019190915290891660608201527f328046a1d3c347f7c3d899996e157a00e5dea81e212c70683d5e4e3f7356ef20608082015260001960a0820152633eb0617f60e11b90309060009060c00160408051601f19818403018152908290526115c99392916024016132ef565b604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050508160038151811061160f5761160f613206565b60209081029190910101526040516001600160a01b038916602482015260001960448201527f328046a1d3c347f7c3d899996e157a00e5dea81e212c70683d5e4e3f7356ef206064820152638cd2e0c760e01b90608401604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b038381831617835250505050816004815181106116ac576116ac613206565b6020908102919091010152604051631592ca1b60e31b81526001600160a01b037f000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc5169063ac9650d890611703908490600401613325565b6000604051808303816000875af1158015611722573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261174a9190810190613387565b50505050505050505050565b604051636eb1769f60e11b81523060048201526001600160a01b03828116602483015283169063dd62ed3e90604401602060405180830381865afa1580156117a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117c69190612e0e565b6000036118435760405163095ea7b360e01b81526001600160a01b038281166004830152600019602483015283169063095ea7b3906044016020604051808303816000875af115801561181d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118419190613437565b505b5050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b179052611841908490612869565b60008060008060007f000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc56001600160a01b03166379502c556040518163ffffffff1660e01b8152600401602060405180830381865afa1580156118ff573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119239190612df1565b60405163b26ec9af60e01b8152600481018a90529091506000906001600160a01b037f000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc5169063b26ec9af906024016020604051808303816000875af1158015611990573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b49190612e0e565b60405163051ff3a360e21b8152600481018b90529091506000906001600160a01b037f000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc5169063147fce8c906024016020604051808303816000875af1158015611a21573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a459190612e0e565b9050808210611a615750600094508493508392506124b5915050565b886001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ac39190612df1565b604051633e4b135360e21b8152600481018c90529097506000906001600160a01b037f0000000000000000000000000e7401707cd08c03cdb53daef3295ddfb68bba92169063f92c4d4c90602401602060405180830381865afa158015611b2e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b529190613459565b905060007f000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc56001600160a01b031663a6d35d796040518163ffffffff1660e01b8152600401602060405180830381865afa158015611bb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611bd89190612df1565b90506001600160a01b03811663b4fc94948385611bfd670de0b6b3a764000089613232565b611c0791906132cd565b8c8e6001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015611c46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c6a9190612df1565b6040516001600160e01b031960e087901b16815261ffff909416600485015260248401929092526001600160a01b039081166044840152166064820152608401602060405180830381865afa158015611cc7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ceb9190612e0e565b95505084600003611d3e5760405162461bcd60e51b815260206004820181905260248201527f4c69717569646174696f6e426f743a20504f534954494f4e5f4845414c5448596044820152606401610427565b6040516369fc8a8560e01b815261ffff82166004820152600090612710907f000000000000000000000000000000000000000000000000000000000000270f906001600160a01b038816906369fc8a8590602401602060405180830381865afa158015611daf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611dd39190612e0e565b611ddd9190613232565b611de791906132cd565b60405163fea1a64f60e01b815261ffff841660048201526001600160a01b038c8116602483015291925060009187169063fea1a64f906044016040805180830381865afa158015611e3c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e609190613499565b60405163fea1a64f60e01b815261ffff851660048201526001600160a01b038e8116602483015291925060009188169063fea1a64f906044016040805180830381865afa158015611eb5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ed99190613499565b90506000611eef670de0b6b3a764000088613232565b611ef98786613232565b611f0391906132a4565b9050600082602001516001600160801b031685611f209190613232565b8451909150611f39908b906001600160801b0316613232565b611f4390826132a4565b9050611f5882670de0b6b3a7640000836124be565b9b505050505050505050600080600060026001600160401b03811115611f8057611f80612b10565b604051908082528060200260200182016040528015611fa9578160200160208202803683370190505b5090508781600081518110611fc057611fc0613206565b60200260200101906001600160a01b031690816001600160a01b031681525050886001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa15801561201e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120429190612df1565b8160018151811061205557612055613206565b6001600160a01b0392831660209182029290920101526040516308f114af60e21b81526000917f0000000000000000000000004e195a32b2f6eba9c4565ba49bef34f23c2c035016906323c452bc906120b29085906004016134f3565b600060405180830381865afa1580156120cf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526120f79190810190613540565b90508060008151811061210c5761210c613206565b602002602001015193508060018151811061212957612129613206565b602002602001015192505050818661214191906132cd565b6040516333bc0c1160e21b8152600481018290529096506001600160a01b038a169063cef0304490602401602060405180830381865afa158015612189573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121ad9190612e0e565b6040516310e28e7160e01b8152600481018c90526001600160a01b038b811660248301529196506000917f0000000000000000000000000e7401707cd08c03cdb53daef3295ddfb68bba9216906310e28e7190604401602060405180830381865afa158015612220573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122449190612e0e565b905061225086826125a8565b6040516318ddac3960e11b8152600481018290529096506001600160a01b038b1691506331bb587290602401602060405180830381865afa158015612299573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122bd9190612e0e565b95506000670de0b6b3a76400006122d48689613232565b6122de91906132cd565b90506000826122ed8584613232565b6122f791906132cd565b60405163402414b360e01b8152600481018e90526001600160a01b038c811660248301529192506000917f0000000000000000000000000e7401707cd08c03cdb53daef3295ddfb68bba92169063402414b390604401602060405180830381865afa15801561236a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061238e9190612e0e565b604051630c1e134760e11b8152600481018290529091506000906001600160a01b038d169063183c268e90602401602060405180830381865afa1580156123d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123fd9190612e0e565b9050828110156124ad576000866124148784613232565b61241e91906132cd565b905088612433670de0b6b3a764000083613232565b61243d91906132cd565b6040516333bc0c1160e21b815260048101829052909b506001600160a01b038f169063cef0304490602401602060405180830381865afa158015612485573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124a99190612e0e565b9950505b505050505050505b93509350935093565b60008080600019858709858702925082811083820303915050806000036124f8578382816124ee576124ee6132b7565b0492505050611076565b80841161253f5760405162461bcd60e51b81526020600482015260156024820152744d6174683a206d756c446976206f766572666c6f7760581b6044820152606401610427565b60008486880960026001871981018816978890046003810283188082028403028082028403028082028403028082028403028082028403029081029092039091026000889003889004909101858311909403939093029303949094049190911702949350505050565b60008183106125b757816125b9565b825b90505b92915050565b600080846001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015612603573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126279190612df1565b90506000846001600160a01b0316632495a5996040518163ffffffff1660e01b8152600401602060405180830381865afa158015612669573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061268d9190612df1565b905060007f000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc56001600160a01b0316637dc0d1d06040518163ffffffff1660e01b8152600401602060405180830381865afa1580156126ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127139190612df1565b6040805160028082526060820183529293506000929091602083019080368337019050509050838160008151811061274d5761274d613206565b60200260200101906001600160a01b031690816001600160a01b031681525050828160018151811061278157612781613206565b6001600160a01b0392831660209182029290920101526040516308f114af60e21b81526000918416906323c452bc906127be9085906004016134f3565b600060405180830381865afa1580156127db573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526128039190810190613540565b905060008160008151811061281a5761281a613206565b6020026020010151905060008260018151811061283957612839613206565b6020026020010151905081818a6128509190613232565b61285a91906132cd565b9b9a5050505050505050505050565b60006128be826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b031661293e9092919063ffffffff16565b90508051600014806128df5750808060200190518101906128df9190613437565b6118415760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610427565b606061061a848460008585600080866001600160a01b031685876040516129659190612f00565b60006040518083038185875af1925050503d80600081146129a2576040519150601f19603f3d011682016040523d82523d6000602084013e6129a7565b606091505b50915091506129b8878383876129c3565b979650505050505050565b60608315612a32578251600003612a2b576001600160a01b0385163b612a2b5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610427565b508161061a565b61061a8383815115612a475781518083602001fd5b8060405162461bcd60e51b81526004016104279190612dde565b6001600160a01b0381168114612a7657600080fd5b50565b600080600080600080600080610100898b031215612a9657600080fd5b883597506020890135612aa881612a61565b96506040890135612ab881612a61565b95506060890135612ac881612a61565b94506080890135612ad881612a61565b935060a0890135612ae881612a61565b925060c0890135612af881612a61565b8092505060e089013590509295985092959890939650565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715612b4e57612b4e612b10565b604052919050565b60006001600160401b03821115612b6f57612b6f612b10565b50601f01601f191660200190565b60008060008060808587031215612b9357600080fd5b8435612b9e81612a61565b93506020850135612bae81612a61565b92506040850135915060608501356001600160401b03811115612bd057600080fd5b8501601f81018713612be157600080fd5b8035612bf4612bef82612b56565b612b26565b818152886020838501011115612c0957600080fd5b8160208401602083013760006020838301015280935050505092959194509250565b600080600080600080600060e0888a031215612c4657600080fd5b873596506020880135612c5881612a61565b95506040880135612c6881612a61565b94506060880135612c7881612a61565b93506080880135612c8881612a61565b925060a0880135612c9881612a61565b8092505060c0880135905092959891949750929550565b600060208284031215612cc157600080fd5b5035919050565b600080600060608486031215612cdd57600080fd5b833592506020840135612cef81612a61565b91506040840135612cff81612a61565b809150509250925092565b600080600060408486031215612d1f57600080fd5b8335612d2a81612a61565b925060208401356001600160401b0380821115612d4657600080fd5b818601915086601f830112612d5a57600080fd5b813581811115612d6957600080fd5b876020828501011115612d7b57600080fd5b6020830194508093505050509250925092565b60005b83811015612da9578181015183820152602001612d91565b50506000910152565b60008151808452612dca816020860160208601612d8e565b601f01601f19169290920160200192915050565b6020815260006125b96020830184612db2565b600060208284031215612e0357600080fd5b815161107681612a61565b600060208284031215612e2057600080fd5b5051919050565b6001600160a01b0387811682528681166020830152858116604083015260c082019060028610612e6757634e487b7160e01b600052602160045260246000fd5b8560608401528085166080840152508260a0830152979650505050505050565b600082601f830112612e9857600080fd5b8151612ea6612bef82612b56565b818152846020838601011115612ebb57600080fd5b61061a826020830160208701612d8e565b600060208284031215612ede57600080fd5b81516001600160401b03811115612ef457600080fd5b61061a84828501612e87565b60008251612f12818460208701612d8e565b9190910192915050565b6020808252602a908201527f4c69717569646174696f6e426f743a20494e53554646494349454e545f4f555460408201526914155517d05353d5539560b21b606082015260800190565b60006001600160401b03821115612f7f57612f7f612b10565b5060051b60200190565b600082601f830112612f9a57600080fd5b81516020612faa612bef83612f66565b82815260059290921b84018101918181019086841115612fc957600080fd5b8286015b84811015612fed578051612fe081612a61565b8352918301918301612fcd565b509695505050505050565b600082601f83011261300957600080fd5b81516020613019612bef83612f66565b82815260059290921b8401810191818101908684111561303857600080fd5b8286015b84811015612fed578051835291830191830161303c565b600082601f83011261306457600080fd5b81516020613074612bef83612f66565b82815260059290921b8401810191818101908684111561309357600080fd5b8286015b84811015612fed5780516001600160401b038111156130b65760008081fd5b6130c48986838b0101612ff8565b845250918301918301613097565b600080600080600060a086880312156130ea57600080fd5b85516001600160401b038082111561310157600080fd5b61310d89838a01612f89565b9650602088015191508082111561312357600080fd5b61312f89838a01612ff8565b9550604088015191508082111561314557600080fd5b61315189838a01612f89565b9450606088015191508082111561316757600080fd5b61317389838a01613053565b9350608088015191508082111561318957600080fd5b5061319688828901613053565b9150509295509295909350565b600080604083850312156131b657600080fd5b82516001600160401b03808211156131cd57600080fd5b6131d986838701612f89565b935060208501519150808211156131ef57600080fd5b506131fc85828601612ff8565b9150509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176125bc576125bc61321c565b600080600080600060a0868803121561326157600080fd5b853561326c81612a61565b9450602086013561327c81612a61565b9350604086013561328c81612a61565b94979396509394606081013594506080013592915050565b818103818111156125bc576125bc61321c565b634e487b7160e01b600052601260045260246000fd5b6000826132ea57634e487b7160e01b600052601260045260246000fd5b500490565b6001600160a01b038416815260ff8316602082015260606040820181905260009061331c90830184612db2565b95945050505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b8281101561337a57603f19888603018452613368858351612db2565b9450928501929085019060010161334c565b5092979650505050505050565b6000602080838503121561339a57600080fd5b82516001600160401b03808211156133b157600080fd5b818501915085601f8301126133c557600080fd5b81516133d3612bef82612f66565b81815260059190911b830184019084810190888311156133f257600080fd5b8585015b8381101561342a5780518581111561340e5760008081fd5b61341c8b89838a0101612e87565b8452509186019186016133f6565b5098975050505050505050565b60006020828403121561344957600080fd5b8151801515811461107657600080fd5b60006020828403121561346b57600080fd5b815161ffff8116811461107657600080fd5b80516001600160801b038116811461349457600080fd5b919050565b6000604082840312156134ab57600080fd5b604051604081018181106001600160401b03821117156134cd576134cd612b10565b6040526134d98361347d565b81526134e76020840161347d565b60208201529392505050565b6020808252825182820181905260009190848201906040850190845b818110156135345783516001600160a01b03168352928401929184019160010161350f565b50909695505050505050565b60006020828403121561355257600080fd5b81516001600160401b0381111561356857600080fd5b61061a84828501612ff856fea2646970667358221220cd826fe5b0dd4057a1ee0346428aee674996c290beb7089a6aabf80e7b1d688d64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc50000000000000000000000000e7401707cd08c03cdb53daef3295ddfb68bba9200000000000000000000000094670598e98f8dad95d85932dd85cbd050ce14020000000000000000000000004403f4296bef042a08785077d67f4700478800c500000000000000000000000078c1b0c915c4faa5fffa6cabf0219da63d7f4cb8000000000000000000000000000000000000000000000000000000000000270f
-----Decoded View---------------
Arg [0] : _core (address): 0x972BcB0284cca0152527c4f70f8F689852bCAFc5
Arg [1] : _posManager (address): 0x0e7401707CD08c03CDb53DAEF3295DDFb68BBa92
Arg [2] : _registry (address): 0x94670598E98f8DAd95D85932dD85CBD050CE1402
Arg [3] : _lens (address): 0x4403F4296BeF042a08785077D67F4700478800C5
Arg [4] : _wNative (address): 0x78c1b0C915c4FAA5FffA6CAbf0219DA63d7f4cb8
Arg [5] : _bufferBPS (uint256): 9999
-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000972bcb0284cca0152527c4f70f8f689852bcafc5
Arg [1] : 0000000000000000000000000e7401707cd08c03cdb53daef3295ddfb68bba92
Arg [2] : 00000000000000000000000094670598e98f8dad95d85932dd85cbd050ce1402
Arg [3] : 0000000000000000000000004403f4296bef042a08785077d67f4700478800c5
Arg [4] : 00000000000000000000000078c1b0c915c4faa5fffa6cabf0219da63d7f4cb8
Arg [5] : 000000000000000000000000000000000000000000000000000000000000270f
Net Worth in USD
Net Worth in MNT
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.