Contract Overview
Balance:
0 ETH
ETH Value:
$0.00
My Name Tag:
Not Available
Txn Hash | Method |
Block
|
From
|
To
|
Value | [Txn Fee] | |||
---|---|---|---|---|---|---|---|---|---|
0xf4c500d9e79dae22bc2a23cf77a9ff3f21866666ee0a5b16785151faa168ff5a | 0x61016060 | 55046014 | 430 days 8 hrs ago | 0xc1e5e997ea88eb0aa18af4cede444be8c8e1e2c1 | IN | Create: Auction | 0 ETH | 0.00293699 |
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Auction
Compiler Version
v0.8.12+commit.f00d7308
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@solidstate/contracts/introspection/ERC165Storage.sol"; import "@solidstate/contracts/utils/Multicall.sol"; import "@solidstate/contracts/utils/ReentrancyGuard.sol"; import "./AuctionInternal.sol"; import "./IAuction.sol"; /** * @title Knox Dutch Auction Contract * @dev deployed standalone and referenced by AuctionProxy */ contract Auction is AuctionInternal, IAuction, Multicall, ReentrancyGuard { using ABDKMath64x64 for int128; using AuctionStorage for AuctionStorage.Layout; using EnumerableSet for EnumerableSet.UintSet; using ERC165Storage for ERC165Storage.Layout; using OrderBook for OrderBook.Index; using SafeERC20 for IERC20; int128 private constant ONE_64x64 = 0x10000000000000000; constructor( bool isCall, address pool, address vault, address weth ) AuctionInternal(isCall, pool, vault, weth) {} /************************************************ * ADMIN ***********************************************/ /** * @inheritdoc IAuction */ function setDeltaOffset64x64(int128 newDeltaOffset64x64) external onlyOwner { AuctionStorage.Layout storage l = AuctionStorage.layout(); require(newDeltaOffset64x64 > 0, "delta <= 0"); require(newDeltaOffset64x64 < ONE_64x64, "delta > 1"); emit DeltaOffsetSet( l.deltaOffset64x64, newDeltaOffset64x64, msg.sender ); l.deltaOffset64x64 = newDeltaOffset64x64; } /** * @inheritdoc IAuction */ function setExchangeHelper(address newExchangeHelper) external onlyOwner { AuctionStorage.Layout storage l = AuctionStorage.layout(); require(newExchangeHelper != address(0), "address not provided"); require( newExchangeHelper != address(l.Exchange), "new address equals old" ); emit ExchangeHelperSet( address(l.Exchange), newExchangeHelper, msg.sender ); l.Exchange = IExchangeHelper(newExchangeHelper); } /** * @inheritdoc IAuction */ function setMinSize(uint256 newMinSize) external onlyOwner { AuctionStorage.Layout storage l = AuctionStorage.layout(); require(newMinSize > 0, "value exceeds minimum"); emit MinSizeSet(l.minSize, newMinSize, msg.sender); l.minSize = newMinSize; } /** * @inheritdoc IAuction */ function setPricer(address newPricer) external onlyOwner { AuctionStorage.Layout storage l = AuctionStorage.layout(); require(newPricer != address(0), "address not provided"); require(newPricer != address(l.Pricer), "new address equals old"); emit PricerSet(address(l.Pricer), newPricer, msg.sender); l.Pricer = IPricer(newPricer); } /************************************************ * INITIALIZE AUCTION ***********************************************/ /** * @inheritdoc IAuction */ function initialize(AuctionStorage.InitAuction memory initAuction) external onlyVault { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[initAuction.epoch]; require( auction.status == AuctionStorage.Status.UNINITIALIZED, "status != uninitialized" ); if ( initAuction.startTime >= initAuction.endTime || block.timestamp > initAuction.startTime || block.timestamp > initAuction.expiry || initAuction.strike64x64 <= 0 || initAuction.longTokenId <= 0 ) { // the auction is cancelled if the start time is greater than or equal to // the end time, the current time is greater than the start time, or the // option parameters are invalid _cancel(l.auctions[initAuction.epoch], initAuction.epoch); } else { auction.expiry = initAuction.expiry; auction.strike64x64 = initAuction.strike64x64; auction.startTime = initAuction.startTime; auction.endTime = initAuction.endTime; auction.longTokenId = initAuction.longTokenId; _updateStatus( auction, AuctionStorage.Status.INITIALIZED, initAuction.epoch ); } } /** * @inheritdoc IAuction */ function setAuctionPrices(uint64 epoch) external { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; require( AuctionStorage.Status.INITIALIZED == auction.status, "status != initialized" ); require( block.timestamp > auction.startTime - 30 minutes, "price set too early" ); require( auction.minPrice64x64 <= 0 || auction.maxPrice64x64 <= 0, "prices are already set" ); if (auction.startTime > block.timestamp) { int128 spot64x64; int128 timeToMaturity64x64; // fetches the spot price of the underlying try l.Pricer.latestAnswer64x64() returns (int128 _spot64x64) { spot64x64 = _spot64x64; } catch Error(string memory message) { emit Log(message); spot64x64 = 0; } // fetches the time to maturity of the option try l.Pricer.getTimeToMaturity64x64(auction.expiry) returns ( int128 _timeToMaturity64x64 ) { timeToMaturity64x64 = _timeToMaturity64x64; } catch Error(string memory message) { emit Log(message); timeToMaturity64x64 = 0; } if (spot64x64 > 0 && timeToMaturity64x64 > 0) { _setAuctionPrices( l, auction, epoch, spot64x64, timeToMaturity64x64 ); } } _validateAuctionPrices(auction, epoch); } /************************************************ * PRICING ***********************************************/ /** * @inheritdoc IAuction */ function lastPrice64x64(uint64 epoch) external view returns (int128) { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; return _lastPrice64x64(auction); } /** * @inheritdoc IAuction */ function priceCurve64x64(uint64 epoch) external view returns (int128) { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; return _priceCurve64x64(auction); } /** * @inheritdoc IAuction */ function clearingPrice64x64(uint64 epoch) external view returns (int128) { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; return _clearingPrice64x64(auction); } /************************************************ * PURCHASE ***********************************************/ /** * @inheritdoc IAuction */ function addLimitOrder( uint64 epoch, int128 price64x64, uint256 size ) external payable nonReentrant { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; _limitOrdersAllowed(auction); uint256 cost = _validateLimitOrder(l, price64x64, size); uint256 credited = _wrapNativeToken(cost); // an approve() by the msg.sender is required beforehand ERC20.safeTransferFrom(msg.sender, address(this), cost - credited); _addOrder(l, auction, epoch, price64x64, size, true); } /** * @inheritdoc IAuction */ function swapAndAddLimitOrder( IExchangeHelper.SwapArgs calldata s, uint64 epoch, int128 price64x64, uint256 size ) external payable nonReentrant { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; _limitOrdersAllowed(auction); uint256 cost = _validateLimitOrder(l, price64x64, size); uint256 credited = _swapForPoolTokens(l.Exchange, s, address(ERC20)); _transferAssets(credited, cost, msg.sender); _addOrder(l, auction, epoch, price64x64, size, true); } /** * @inheritdoc IAuction */ function cancelLimitOrder(uint64 epoch, uint128 orderId) external nonReentrant { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; _limitOrdersAllowed(auction); require(orderId > 0, "invalid order id"); OrderBook.Index storage orderbook = l.orderbooks[epoch]; OrderBook.Data memory data = orderbook._getOrderById(orderId); require(data.buyer != address(0), "order does not exist"); require(data.buyer == msg.sender, "buyer != msg.sender"); orderbook._remove(orderId); // removes unique order id associated with epoch and id _removeUniqueOrderId(l, epoch, orderId); if (block.timestamp >= auction.startTime) { _finalizeAuction(l, auction, epoch); } uint256 cost = data.price64x64.mulu(data.size); ERC20.safeTransfer(msg.sender, cost); emit OrderCanceled(epoch, orderId, msg.sender); } /** * @inheritdoc IAuction */ function addMarketOrder( uint64 epoch, uint256 size, uint256 maxCost ) external payable nonReentrant { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; _marketOrdersAllowed(auction); (int128 price64x64, uint256 cost) = _validateMarketOrder(l, auction, size, maxCost); uint256 credited = _wrapNativeToken(cost); // an approve() by the msg.sender is required beforehand ERC20.safeTransferFrom(msg.sender, address(this), cost - credited); _addOrder(l, auction, epoch, price64x64, size, false); } /** * @inheritdoc IAuction */ function swapAndAddMarketOrder( IExchangeHelper.SwapArgs calldata s, uint64 epoch, uint256 size, uint256 maxCost ) external payable nonReentrant { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; _marketOrdersAllowed(auction); (int128 price64x64, uint256 cost) = _validateMarketOrder(l, auction, size, maxCost); uint256 credited = _swapForPoolTokens(l.Exchange, s, address(ERC20)); _transferAssets(credited, cost, msg.sender); _addOrder(l, auction, epoch, price64x64, size, false); } /************************************************ * WITHDRAW ***********************************************/ /** * @inheritdoc IAuction */ function withdraw(uint64 epoch) external nonReentrant { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; require( AuctionStorage.Status.PROCESSED == auction.status || AuctionStorage.Status.CANCELLED == auction.status, "status != processed || cancelled" ); if (AuctionStorage.Status.PROCESSED == auction.status) { // long tokens are withheld for 24 hours after the auction has been processed, otherwise // if a long position is exercised within 24 hours of the position being underwritten // the collateral from the position will be moved to the pools "free liquidity" queue. require( block.timestamp >= auction.processedTime + 24 hours, "hold period has not ended" ); } _withdraw(l, epoch); } /** * @inheritdoc IAuction */ function previewWithdraw(uint64 epoch) external returns (uint256, uint256) { return _previewWithdraw(epoch, msg.sender); } /** * @inheritdoc IAuction */ function previewWithdraw(uint64 epoch, address buyer) external returns (uint256, uint256) { return _previewWithdraw(epoch, buyer); } /************************************************ * FINALIZE AUCTION ***********************************************/ /** * @inheritdoc IAuction */ function finalizeAuction(uint64 epoch) external { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; if ( block.timestamp > auction.endTime + 24 hours && (auction.status == AuctionStorage.Status.INITIALIZED || auction.status == AuctionStorage.Status.FINALIZED) ) { // cancel the auction if it has not been processed within 24 hours of the // auction end time so that buyers may withdraw their refunded amount _cancel(auction, epoch); } else if ( block.timestamp >= auction.startTime && auction.status == AuctionStorage.Status.INITIALIZED ) { // finalize the auction only if the auction has started _finalizeAuction(l, auction, epoch); } } /** * @inheritdoc IAuction */ function processAuction(uint64 epoch) external onlyVault returns (uint256, uint256) { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; require( AuctionStorage.Status.FINALIZED == auction.status, "status != finalized" ); auction.totalPremiums = _lastPrice64x64(auction).mulu( auction.totalContractsSold ); ERC20.safeTransfer(address(Vault), auction.totalPremiums); auction.processedTime = block.timestamp; _updateStatus(auction, AuctionStorage.Status.PROCESSED, epoch); return (auction.totalPremiums, auction.totalContractsSold); } /************************************************ * VIEW ***********************************************/ /** * @inheritdoc IAuction */ function getAuction(uint64 epoch) external view returns (AuctionStorage.Auction memory) { return AuctionStorage._getAuction(epoch); } /** * @inheritdoc IAuction */ function getDeltaOffset64x64() external view returns (int128) { return AuctionStorage._getDeltaOffset64x64(); } /** * @inheritdoc IAuction */ function getMinSize() external view returns (uint256) { return AuctionStorage._getMinSize(); } /** * @inheritdoc IAuction */ function getOrderById(uint64 epoch, uint128 orderId) external view returns (OrderBook.Data memory) { return AuctionStorage._getOrderById(epoch, orderId); } /** * @inheritdoc IAuction */ function getStatus(uint64 epoch) external view returns (AuctionStorage.Status) { return AuctionStorage._getStatus(epoch); } /** * @inheritdoc IAuction */ function getTotalContracts(uint64 epoch) external view returns (uint256) { AuctionStorage.Layout storage l = AuctionStorage.layout(); AuctionStorage.Auction storage auction = l.auctions[epoch]; // returns the stored total contracts if the auction has started if (auction.startTime > 0 && block.timestamp >= auction.startTime) { return AuctionStorage._getTotalContracts(epoch); } return 0; } /** * @inheritdoc IAuction */ function getTotalContractsSold(uint64 epoch) external view returns (uint256) { return AuctionStorage._getTotalContractsSold(epoch); } /** * @inheritdoc IAuction */ function getUniqueOrderIds(address buyer) external view returns (uint256[] memory) { AuctionStorage.Layout storage l = AuctionStorage.layout(); EnumerableSet.UintSet storage uoids = l.uoids[buyer]; uint256[] memory _uoids = new uint256[](uoids.length()); unchecked { for (uint256 i; i < uoids.length(); ++i) { uint256 uoid = uoids.at(i); _uoids[i] = uoid; } } return _uoids; } /************************************************ * ERC165 SUPPORT ***********************************************/ /** * @inheritdoc IERC165 */ function supportsInterface(bytes4 interfaceId) external view returns (bool) { return ERC165Storage.layout().isSupportedInterface(interfaceId); } /************************************************ * ERC1155 SUPPORT ***********************************************/ /** * @inheritdoc IERC1155Receiver */ function onERC1155Received( address, address, uint256, uint256, bytes memory ) external pure returns (bytes4) { return this.onERC1155Received.selector; } /** * @inheritdoc IERC1155Receiver */ function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) external pure returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library ERC165Storage { struct Layout { mapping(bytes4 => bool) supportedInterfaces; } bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.ERC165'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } function isSupportedInterface(Layout storage l, bytes4 interfaceId) internal view returns (bool) { return l.supportedInterfaces[interfaceId]; } function setSupportedInterface( Layout storage l, bytes4 interfaceId, bool status ) internal { require(interfaceId != 0xffffffff, 'ERC165: invalid interface id'); l.supportedInterfaces[interfaceId] = status; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IMulticall } from './IMulticall.sol'; /** * @title Utility contract for supporting processing of multiple function calls in a single transaction */ abstract contract Multicall is IMulticall { /** * @inheritdoc IMulticall */ function multicall(bytes[] calldata data) external returns (bytes[] memory results) { results = new bytes[](data.length); unchecked { for (uint256 i; i < data.length; i++) { (bool success, bytes memory returndata) = address(this) .delegatecall(data[i]); if (success) { results[i] = returndata; } else { assembly { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } } } } return results; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { ReentrancyGuardStorage } from './ReentrancyGuardStorage.sol'; /** * @title Utility contract for preventing reentrancy attacks */ abstract contract ReentrancyGuard { modifier nonReentrant() { ReentrancyGuardStorage.Layout storage l = ReentrancyGuardStorage .layout(); require(l.status != 2, 'ReentrancyGuard: reentrant call'); l.status = 2; _; l.status = 1; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@solidstate/contracts/access/ownable/OwnableInternal.sol"; import "@solidstate/contracts/token/ERC1155/IERC1155.sol"; import "@solidstate/contracts/token/ERC20/IERC20.sol"; import "@solidstate/contracts/token/ERC20/metadata/IERC20Metadata.sol"; import "@solidstate/contracts/utils/IWETH.sol"; import "@solidstate/contracts/utils/SafeCast.sol"; import "@solidstate/contracts/utils/SafeERC20.sol"; import "../libraries/OptionMath.sol"; import "../vendor/IPremiaPool.sol"; import "../vault/IVault.sol"; import "./AuctionStorage.sol"; import "./IAuctionEvents.sol"; /** * @title Knox Dutch Auction Internal Contract */ contract AuctionInternal is IAuctionEvents, OwnableInternal { using ABDKMath64x64 for int128; using ABDKMath64x64 for uint256; using ABDKMath64x64Token for int128; using ABDKMath64x64Token for uint256; using AuctionStorage for AuctionStorage.Layout; using EnumerableSet for EnumerableSet.UintSet; using OptionMath for uint256; using OrderBook for OrderBook.Index; using SafeCast for uint256; using SafeERC20 for IERC20; using SafeERC20 for IWETH; bool internal immutable isCall; uint8 internal immutable baseDecimals; uint8 internal immutable underlyingDecimals; IERC20 public immutable ERC20; IPremiaPool public immutable Pool; IVault public immutable Vault; IWETH public immutable WETH; constructor( bool _isCall, address pool, address vault, address weth ) { isCall = _isCall; Pool = IPremiaPool(pool); IPremiaPool.PoolSettings memory settings = Pool.getPoolSettings(); address asset = isCall ? settings.underlying : settings.base; baseDecimals = IERC20Metadata(settings.base).decimals(); underlyingDecimals = IERC20Metadata(settings.underlying).decimals(); ERC20 = IERC20(asset); Vault = IVault(vault); WETH = IWETH(weth); } /************************************************ * ACCESS CONTROL ***********************************************/ /** * @dev Throws if called by any account other than the vault */ modifier onlyVault() { AuctionStorage.Layout storage l = AuctionStorage.layout(); require(msg.sender == address(Vault), "!vault"); _; } /** * @dev Throws if limit orders are not allowed * @param auction storage params */ function _limitOrdersAllowed(AuctionStorage.Auction storage auction) internal view { require( AuctionStorage.Status.INITIALIZED == auction.status, "status != initialized" ); _auctionHasNotEnded(auction); } /** * @dev Throws if market orders are not allowed * @param auction storage params */ function _marketOrdersAllowed(AuctionStorage.Auction storage auction) internal view { require( AuctionStorage.Status.INITIALIZED == auction.status, "status != initialized" ); _auctionHasStarted(auction); _auctionHasNotEnded(auction); } /** * @dev Throws if auction has not started. * @param auction storage params */ function _auctionHasStarted(AuctionStorage.Auction storage auction) private view { require(auction.startTime > 0, "start time is not set"); require(block.timestamp >= auction.startTime, "auction not started"); } /** * @dev Throws if auction has ended. * @param auction storage params */ function _auctionHasNotEnded(AuctionStorage.Auction storage auction) private view { require(auction.endTime > 0, "end time is not set"); require(block.timestamp <= auction.endTime, "auction has ended"); } /************************************************ * PRICING ***********************************************/ /** * @notice returns the last price paid during the auction * @param auction storage params * @return price as 64x64 fixed point number */ function _lastPrice64x64(AuctionStorage.Auction storage auction) internal view returns (int128) { return auction.lastPrice64x64; } /** * @notice calculates the current price using the price curve function * @param auction storage params * @return price as 64x64 fixed point number */ function _priceCurve64x64(AuctionStorage.Auction storage auction) internal view returns (int128) { uint256 startTime = auction.startTime; uint256 totalTime = auction.endTime - auction.startTime; int128 maxPrice64x64 = auction.maxPrice64x64; int128 minPrice64x64 = auction.minPrice64x64; /** * * price curve equation: * assumes max price is always greater than min price * assumes the time remaining is in the range of 0 and 1 * ------------------------------ * time_remaning_percent(t) = (t - time_start) / time_total * price(t) = max_price - time_remaning_percent(t) * (max_price - min_price) * */ if (block.timestamp <= startTime) return maxPrice64x64; if (block.timestamp >= auction.endTime) return minPrice64x64; uint256 elapsed = block.timestamp - startTime; int128 timeRemaining64x64 = elapsed.divu(totalTime); int128 x = maxPrice64x64.sub(minPrice64x64); int128 y = timeRemaining64x64.mul(x); return maxPrice64x64.sub(y); } /** * @notice returns the current price established by the price curve if the auction * is still ongoing, otherwise the last price paid is returned * @param auction storage params * @return price as 64x64 fixed point number */ function _clearingPrice64x64(AuctionStorage.Auction storage auction) internal view returns (int128) { if ( auction.status == AuctionStorage.Status.FINALIZED || auction.status == AuctionStorage.Status.PROCESSED || auction.status == AuctionStorage.Status.CANCELLED ) { return _lastPrice64x64(auction); } return _priceCurve64x64(auction); } /** * @notice calculates and sets the option max and min price * @param l auction storage layout * @param auction storage params * @param epoch epoch id * @param spot64x64 spot price of the underlying as 64x64 fixed point number * @param timeToMaturity64x64 time remaining until maturity as a 64x64 fixed point number */ function _setAuctionPrices( AuctionStorage.Layout storage l, AuctionStorage.Auction storage auction, uint64 epoch, int128 spot64x64, int128 timeToMaturity64x64 ) internal { int128 strike64x64 = auction.strike64x64; // calculates the further OTM strike price int128 offsetAmount64x64 = strike64x64.mul(l.deltaOffset64x64); int128 offsetStrike64x64 = isCall ? strike64x64.add(offsetAmount64x64) : strike64x64.sub(offsetAmount64x64); /** * it is assumed that the rounded strike price will always be further ITM than the offset * strike price. the further ITM option will always be more expensive and will therefore * be used to determine the max price of the auction. likewise, the offset strike price * (further OTM) should resemble a cheaper option and it is therefore used as the min * option price in our auction. * * * Call Option * ----------- * Strike Rounded Strike Offset Strike * | ---------> | | * | | | * -----------------------Price------------------------> * * * Put Option * ----------- * Offset Strike Rounded Strike Strike * | | <--------- | * | | | * -----------------------Price------------------------> * * */ // calculates the auction max price using the strike price (further ITM) auction.maxPrice64x64 = l.Pricer.getBlackScholesPrice64x64( spot64x64, strike64x64, timeToMaturity64x64, isCall ); // calculates the auction min price using the offset strike price (further OTM) auction.minPrice64x64 = l.Pricer.getBlackScholesPrice64x64( spot64x64, offsetStrike64x64, timeToMaturity64x64, isCall ); if (isCall) { // denominates price in the collateral asset auction.maxPrice64x64 = auction.maxPrice64x64.div(spot64x64); auction.minPrice64x64 = auction.minPrice64x64.div(spot64x64); } emit AuctionPricesSet( epoch, strike64x64, offsetStrike64x64, spot64x64, auction.maxPrice64x64, auction.minPrice64x64 ); } /** * @notice validates the max and min prices * @param auction storage params * @param epoch epoch id */ function _validateAuctionPrices( AuctionStorage.Auction storage auction, uint64 epoch ) internal { if ( auction.maxPrice64x64 <= 0 || auction.minPrice64x64 <= 0 || auction.maxPrice64x64 <= auction.minPrice64x64 ) { // if either price is 0 or the max price is less than or equal to the min price, // the auction should always be cancelled. _cancel(auction, epoch); } } /************************************************ * WITHDRAW ***********************************************/ /** * @notice withdraws any amount(s) owed to the buyer (fill and/or refund) * @param l auction storage layout * @param epoch epoch id */ function _withdraw(AuctionStorage.Layout storage l, uint64 epoch) internal { (uint256 refund, uint256 fill) = _previewWithdraw(l, false, epoch, msg.sender); // removes all unique order ids associated with epoch _removeUniqueOrderId(l, epoch, 0); // fetches the exercised value of the options (bool expired, uint256 exercisedAmount) = _getExerciseAmount(l, epoch, fill); if (expired) { if (exercisedAmount > 0) { // if expired ITM, adjust refund by the amount exercised refund += exercisedAmount; } // set fill to 0, buyer will not receive any long tokens fill = 0; } if (fill > 0) { // transfers long tokens to msg.sender Pool.safeTransferFrom( address(this), msg.sender, l.auctions[epoch].longTokenId, fill, "" ); } if (refund > 0) { // transfers refunded premium to msg.sender ERC20.safeTransfer(msg.sender, refund); } emit OrderWithdrawn(epoch, msg.sender, refund, fill); } /** * @notice calculates amount(s) owed to the buyer * @param epoch epoch id * @param buyer address of buyer * @return amount refunded * @return amount filled */ function _previewWithdraw(uint64 epoch, address buyer) internal returns (uint256, uint256) { AuctionStorage.Layout storage l = AuctionStorage.layout(); return _previewWithdraw(l, true, epoch, buyer); } /** * @notice traverses the orderbook and returns the refund and fill amounts * @param l auction storage layout * @param epoch epoch id * @param buyer address of buyer * @return amount refunded * @return amount filled */ function _previewWithdraw( AuctionStorage.Layout storage l, bool isPreview, uint64 epoch, address buyer ) private returns (uint256, uint256) { AuctionStorage.Auction storage auction = l.auctions[epoch]; OrderBook.Index storage orderbook = l.orderbooks[epoch]; uint256 refund; uint256 fill; int128 lastPrice64x64 = _clearingPrice64x64(auction); uint256 totalUnclaimedContracts = auction.totalUnclaimedContracts; // traverse the order book and return orders placed by the buyer until the end of the orderbook has been reached OrderBook.Data memory data = orderbook._getOrderById(orderbook._head()); do { uint256 next = orderbook._getNextOrder(data.id); if (data.buyer == buyer) { uint256 claimed; uint256 paid = data.price64x64.mulu(data.size); if ( auction.status != AuctionStorage.Status.CANCELLED && totalUnclaimedContracts > 0 && data.price64x64 >= lastPrice64x64 ) { // if the auction has not been cancelled, and the order price is greater than or // equal to the last price, fill the order and calculate the refund amount uint256 cost = lastPrice64x64.mulu(data.size); if (data.size > totalUnclaimedContracts) { // if part of the current order exceeds the total contracts available, partially // fill the order, and refund the remainder cost = lastPrice64x64.mulu(totalUnclaimedContracts); fill += totalUnclaimedContracts; claimed += totalUnclaimedContracts; } else { // otherwise, fill the entire order fill += data.size; claimed += data.size; } // the refund takes the difference between the amount paid and the "true" cost of // of the order. the "true" cost can be calculated when the clearing price has been // set. refund += paid - cost; } else { // if no contracts are available, the auction has been cancelled, or the bid is too // low, only send refund refund += paid; } if (!isPreview) { // if the buyer has a filled order, remove it from the unclaimed // contract balance auction.totalUnclaimedContracts -= claimed; // when a withdrawal is made, remove the order from the order book orderbook._remove(data.id); } // claimed amount is reset after every filled order claimed = 0; } if (totalUnclaimedContracts > 0) { if (data.size > totalUnclaimedContracts) { totalUnclaimedContracts = 0; } else { totalUnclaimedContracts -= data.size; } } data = orderbook._getOrderById(next); } while (data.id != 0); return (refund, fill); } /************************************************ * FINALIZE AUCTION ***********************************************/ /** * @notice traverses the orderbook and checks if the auction has reached 100% utilization * @param l auction storage layout * @param epoch epoch id * @return true if the auction has reached 100% utilization */ function _processOrders(AuctionStorage.Layout storage l, uint64 epoch) private returns (bool) { OrderBook.Index storage orderbook = l.orderbooks[epoch]; AuctionStorage.Auction storage auction = l.auctions[epoch]; // if the total contracts has not been set for the auction, the vault contract will be // queried and the amount will be determined from the collateral in the vault. if (auction.totalContracts <= 0) { uint256 totalContracts = _getTotalContracts(auction); // auction is cancelled if there are no contracts available if (totalContracts <= 0) { _cancel(auction, epoch); return false; } auction.totalContracts = totalContracts; } uint256 totalContractsSold; int128 lastPrice64x64; // traverse the order book and sum the contracts sold until the utilization == 100% or // the end of the orderbook has been reached OrderBook.Data memory data = orderbook._getOrderById(orderbook._head()); do { uint256 next = orderbook._getNextOrder(data.id); // orders in the order book are sorted by price in a descending order. if the // order price < clearing price the last order which should be accepeted has // been reached. if (data.price64x64 < _clearingPrice64x64(auction)) break; // checks if utilization >= 100% if (totalContractsSold + data.size >= auction.totalContracts) { auction.lastPrice64x64 = data.price64x64; auction.totalContractsSold = auction.totalContracts; return true; } totalContractsSold += data.size; lastPrice64x64 = data.price64x64; data = orderbook._getOrderById(next); } while (data.id != 0); /** * sets the last price reached in the order book equal to the last price paid in the auction. * * * Orderbook | price curve == 96 * --------- * id - price * 0 - 100 * 1 - 97 --- last price * 2 - 95 * */ auction.lastPrice64x64 = lastPrice64x64; auction.totalContractsSold = totalContractsSold; return false; } /** * @notice determines whether the auction has reached finality. the end criteria for the auction are * met if the auction has reached 100% utilization or the end time has been exceeded. * @param l auction storage layout * @param auction storage params * @param epoch epoch id */ function _finalizeAuction( AuctionStorage.Layout storage l, AuctionStorage.Auction storage auction, uint64 epoch ) internal { _validateAuctionPrices(auction, epoch); if ( auction.status != AuctionStorage.Status.CANCELLED && (_processOrders(l, epoch) || block.timestamp > auction.endTime) ) { if (auction.totalContractsSold > 0) { auction.totalUnclaimedContracts = auction.totalContractsSold; _updateStatus(auction, AuctionStorage.Status.FINALIZED, epoch); } else { _cancel(auction, epoch); } } } /************************************************ * VIEW ***********************************************/ /** * @notice calculates the total number of contracts that can be sold during the auction * @param auction storage params * @return total contracts available */ function _getTotalContracts(AuctionStorage.Auction storage auction) private view returns (uint256) { uint256 collateral = Vault.totalCollateral(); uint256 reserves = Vault.previewReserves(); return collateral > reserves ? (collateral - reserves).fromCollateralToContracts( isCall, baseDecimals, auction.strike64x64 ) : 0; } /************************************************ * PURCHASE HELPERS ***********************************************/ /** * @notice checks whether the limit order parameters are valid and returns the cost * @param l auction storage layout * @param price64x64 max price as 64x64 fixed point number * @param size amount of contracts * @return cost of the order given the size and price */ function _validateLimitOrder( AuctionStorage.Layout storage l, int128 price64x64, uint256 size ) internal view returns (uint256) { require(price64x64 > 0, "price <= 0"); require(size >= l.minSize, "size < minimum"); uint256 cost = price64x64.mulu(size); return cost; } /** * @notice checks whether the market order parameters are valid and returns the price and cost * @param l auction storage layout * @param auction storage params * @param size amount of contracts * @param maxCost max cost of buyer is willing to pay * @return price established by the price curve * @return cost of the order given the size and price */ function _validateMarketOrder( AuctionStorage.Layout storage l, AuctionStorage.Auction storage auction, uint256 size, uint256 maxCost ) internal view returns (int128, uint256) { require(size >= l.minSize, "size < minimum"); int128 price64x64 = _priceCurve64x64(auction); uint256 cost = price64x64.mulu(size); require(maxCost >= cost, "cost > maxCost"); return (price64x64, cost); } /** * @notice transfers the premium to the buyer if a refund is due, ortherwise, pull funds * from buyer if funds are owed to the auction contract. * @param credited amount already paid by the buyer * @param cost total amount which must be paid by the buyer * @param buyer account being debited or credited */ function _transferAssets( uint256 credited, uint256 cost, address buyer ) internal { if (credited > cost) { // refund buyer the amount overpaid ERC20.safeTransfer(buyer, credited - cost); } else if (cost > credited) { // an approve() by the msg.sender is required beforehand ERC20.safeTransferFrom(buyer, address(this), cost - credited); } } /** * @notice checks whether the market order parameters are valid and returns the price and cost * @param l auction storage layout * @param auction storage params * @param epoch epoch id * @param price64x64 max price as 64x64 fixed point number * @param size amount of contracts * @param isLimitOrder true, if the order is a limit order */ function _addOrder( AuctionStorage.Layout storage l, AuctionStorage.Auction storage auction, uint64 epoch, int128 price64x64, uint256 size, bool isLimitOrder ) internal { uint128 orderId = l.orderbooks[epoch] ._insert(price64x64, size, msg.sender) .toUint128(); // format the unique order id and add it to storage uint256 uoid = AuctionStorage._formatUniqueOrderId(epoch, orderId); l.uoids[msg.sender].add(uoid); if (block.timestamp >= auction.startTime) { _finalizeAuction(l, auction, epoch); } emit OrderAdded( epoch, orderId, msg.sender, price64x64, size, isLimitOrder ); } /** * @notice wraps ETH sent to the contract and credits the amount, if the collateral asset * is not WETH, the transaction will revert * @param amount total collateral deposited * @return credited amount */ function _wrapNativeToken(uint256 amount) internal returns (uint256) { uint256 credit; if (msg.value > 0) { require(address(ERC20) == address(WETH), "collateral != wETH"); if (msg.value > amount) { // if the ETH amount is greater than the amount needed, it will be sent // back to the msg.sender unchecked { (bool success, ) = payable(msg.sender).call{value: msg.value - amount}(""); require(success, "ETH refund failed"); credit = amount; } } else { credit = msg.value; } WETH.deposit{value: credit}(); } return credit; } /** * @notice pull token from user, send to exchangeHelper trigger a trade from * ExchangeHelper, and credits the amount * @param Exchange ExchangeHelper contract interface * @param s swap arguments * @param tokenOut token to swap for. should always equal to the collateral asset * @return credited amount */ function _swapForPoolTokens( IExchangeHelper Exchange, IExchangeHelper.SwapArgs calldata s, address tokenOut ) internal returns (uint256) { if (msg.value > 0) { require(s.tokenIn == address(WETH), "tokenIn != wETH"); WETH.deposit{value: msg.value}(); WETH.safeTransfer(address(Exchange), msg.value); } if (s.amountInMax > 0) { IERC20(s.tokenIn).safeTransferFrom( msg.sender, address(Exchange), s.amountInMax ); } uint256 amountCredited = Exchange.swapWithToken( s.tokenIn, tokenOut, s.amountInMax + msg.value, s.callee, s.allowanceTarget, s.data, s.refundAddress ); require( amountCredited >= s.amountOutMin, "not enough output from trade" ); return amountCredited; } /************************************************ * HELPERS ***********************************************/ /** * @notice cancels all orders and finalizes the auction * @param auction the auction to cancel * @param epoch epoch id */ function _cancel(AuctionStorage.Auction storage auction, uint64 epoch) internal { auction.totalPremiums = 0; _updateStatus(auction, AuctionStorage.Status.CANCELLED, epoch); } /** * @notice calculates the expected proceeds of the option if it has expired * @param epoch epoch id * @param size amount of contracts * @return true if the option has expired * @return the exercised amount */ function _getExerciseAmount( AuctionStorage.Layout storage l, uint64 epoch, uint256 size ) private view returns (bool, uint256) { AuctionStorage.Auction storage auction = l.auctions[epoch]; uint64 expiry = auction.expiry; int128 strike64x64 = auction.strike64x64; if (block.timestamp < expiry) return (false, 0); int128 spot64x64 = Pool.getPriceAfter64x64(expiry); uint256 amount; if (isCall && spot64x64 > strike64x64) { amount = spot64x64.sub(strike64x64).div(spot64x64).mulu(size); } else if (!isCall && strike64x64 > spot64x64) { uint256 value = strike64x64.sub(spot64x64).mulu(size); // converts the value to the base asset amount, this is particularly important where the // the decimals of the underlying are different from the base (e.g. wBTC/DAI) amount = OptionMath.toBaseTokenAmount( underlyingDecimals, baseDecimals, value ); } return (true, amount); } /** * @notice removes the active unique order id from uoids mapping * @param l auction storage layout * @param epoch epoch id * @param orderId order id */ function _removeUniqueOrderId( AuctionStorage.Layout storage l, uint64 epoch, uint128 orderId ) internal { EnumerableSet.UintSet storage uoids = l.uoids[msg.sender]; unchecked { for (uint256 i; i < uoids.length(); ++i) { uint256 uoid = uoids.at(i); (, uint64 _epoch, uint128 _orderId) = AuctionStorage._parseUniqueOrderId(uoid); if ( (orderId == 0 && _epoch == epoch) || (_orderId == orderId && _epoch == epoch) ) { uoids.remove(uoid); } } } } function _updateStatus( AuctionStorage.Auction storage auction, AuctionStorage.Status status, uint64 epoch ) internal { auction.status = status; emit AuctionStatusSet(epoch, auction.status); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@solidstate/contracts/introspection/IERC165.sol"; import "@solidstate/contracts/token/ERC1155/IERC1155Receiver.sol"; import "@solidstate/contracts/utils/IMulticall.sol"; import "../vendor/IExchangeHelper.sol"; import "./AuctionStorage.sol"; import "./IAuctionEvents.sol"; /** * @title Knox Auction Interface */ interface IAuction is IAuctionEvents, IERC165, IERC1155Receiver, IMulticall { /************************************************ * ADMIN ***********************************************/ /** * @notice sets the percent offset from delta strike * @param newDeltaOffset64x64 new percent offset value as a 64x64 fixed point number */ function setDeltaOffset64x64(int128 newDeltaOffset64x64) external; /** * @notice sets a new Exchange Helper contract * @param newExchangeHelper new Exchange Helper contract address */ function setExchangeHelper(address newExchangeHelper) external; /** * @notice sets a new minimum order size * @param newMinSize new minimum order size */ function setMinSize(uint256 newMinSize) external; /** * @notice sets the new pricer * @dev the pricer contract address must be set during the vault initialization * @param newPricer address of the new pricer */ function setPricer(address newPricer) external; /************************************************ * INITIALIZE AUCTION ***********************************************/ /** * @notice initializes a new auction * @param initAuction auction parameters */ function initialize(AuctionStorage.InitAuction memory initAuction) external; /** * @notice sets the auction max/min prices * @param epoch epoch id */ function setAuctionPrices(uint64 epoch) external; /************************************************ * PRICING ***********************************************/ /** * @notice returns the last price paid during the auction * @param epoch epoch id * @return price as 64x64 fixed point number */ function lastPrice64x64(uint64 epoch) external view returns (int128); /** * @notice calculates the current price using the price curve function * @param epoch epoch id * @return price as 64x64 fixed point number */ function priceCurve64x64(uint64 epoch) external view returns (int128); /** * @notice returns the current price established by the price curve if the auction * is still ongoing, otherwise the last price paid is returned * @param epoch epoch id * @return price as 64x64 fixed point number */ function clearingPrice64x64(uint64 epoch) external view returns (int128); /************************************************ * PURCHASE ***********************************************/ /** * @notice adds an order specified by the price and size * @dev sent ETH will be wrapped as wETH, sender must approve contract * @param epoch epoch id * @param price64x64 max price as 64x64 fixed point number * @param size amount of contracts */ function addLimitOrder( uint64 epoch, int128 price64x64, uint256 size ) external payable; /** * @notice swaps into the collateral asset and adds an order specified by the price and size * @dev sent ETH will be wrapped as wETH, sender must approve contract * @param s swap arguments * @param epoch epoch id * @param price64x64 max price as 64x64 fixed point number * @param size amount of contracts */ function swapAndAddLimitOrder( IExchangeHelper.SwapArgs calldata s, uint64 epoch, int128 price64x64, uint256 size ) external payable; /** * @notice cancels an order * @dev sender must approve contract * @param epoch epoch id * @param orderId order id */ function cancelLimitOrder(uint64 epoch, uint128 orderId) external; /** * @notice adds an order specified by size only * @dev sent ETH will be wrapped as wETH, sender must approve contract * @param epoch epoch id * @param size amount of contracts * @param maxCost max cost of buyer is willing to pay */ function addMarketOrder( uint64 epoch, uint256 size, uint256 maxCost ) external payable; /** * @notice swaps into the collateral asset and adds an order specified by size only * @dev sent ETH will be wrapped as wETH, sender must approve contract * @param s swap arguments * @param epoch epoch id * @param size amount of contracts * @param maxCost max cost of buyer is willing to pay */ function swapAndAddMarketOrder( IExchangeHelper.SwapArgs calldata s, uint64 epoch, uint256 size, uint256 maxCost ) external payable; /************************************************ * WITHDRAW ***********************************************/ /** * @notice withdraws any amount(s) owed to the buyer (fill and/or refund) * @param epoch epoch id */ function withdraw(uint64 epoch) external; /** * @notice calculates amount(s) owed to the buyer * @param epoch epoch id * @return amount refunded * @return amount filled */ function previewWithdraw(uint64 epoch) external returns (uint256, uint256); /** * @notice calculates amount(s) owed to the buyer * @param epoch epoch id * @param buyer address of buyer * @return amount refunded * @return amount filled */ function previewWithdraw(uint64 epoch, address buyer) external returns (uint256, uint256); /************************************************ * FINALIZE AUCTION ***********************************************/ /** * @notice determines whether the auction has reached finality. the end criteria for the auction are * met if the auction has reached 100% utilization or the end time has been exceeded. * @param epoch epoch id */ function finalizeAuction(uint64 epoch) external; /** * @notice transfers premiums and updates auction state * @param epoch epoch id * @return amount in premiums paid during auction * @return total number of contracts sold */ function processAuction(uint64 epoch) external returns (uint256, uint256); /************************************************ * VIEW ***********************************************/ /** * @notice returns the auction parameters * @param epoch epoch id * @return auction parameters */ function getAuction(uint64 epoch) external view returns (AuctionStorage.Auction memory); /** * @notice returns percent delta offset * @return percent delta offset as a 64x64 fixed point number */ function getDeltaOffset64x64() external view returns (int128); /** * @notice returns the minimum order size * @return minimum order size */ function getMinSize() external view returns (uint256); /** * @notice returns the order from the auction orderbook * @param epoch epoch id * @param orderId order id * @return order from auction orderbook */ function getOrderById(uint64 epoch, uint128 orderId) external view returns (OrderBook.Data memory); /** * @notice returns the status of the auction * @param epoch epoch id * @return auction status */ function getStatus(uint64 epoch) external view returns (AuctionStorage.Status); /** * @notice returns the stored total number of contracts that can be sold during the auction * returns 0 if the auction has not started * @param epoch epoch id * @return total number of contracts which may be sold */ function getTotalContracts(uint64 epoch) external view returns (uint256); /** * @notice returns the total number of contracts sold * @param epoch epoch id * @return total number of contracts sold */ function getTotalContractsSold(uint64 epoch) external view returns (uint256); /** * @notice returns the active unique order ids * @param buyer address of buyer * @return array of unique order ids */ function getUniqueOrderIds(address buyer) external view returns (uint256[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Interface for the Multicall utility contract */ interface IMulticall { /** * @notice batch function calls to the contract and return the results of each * @param data array of function call data payloads * @return results array of function call results */ function multicall(bytes[] calldata data) external returns (bytes[] memory results); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library ReentrancyGuardStorage { struct Layout { uint256 status; } bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.ReentrancyGuard'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IOwnableInternal } from './IOwnableInternal.sol'; import { OwnableStorage } from './OwnableStorage.sol'; abstract contract OwnableInternal is IOwnableInternal { using OwnableStorage for OwnableStorage.Layout; modifier onlyOwner() { require( msg.sender == OwnableStorage.layout().owner, 'Ownable: sender must be owner' ); _; } function _owner() internal view virtual returns (address) { return OwnableStorage.layout().owner; } function _transferOwnership(address account) internal virtual { OwnableStorage.layout().setOwner(account); emit OwnershipTransferred(msg.sender, account); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC1155Internal } from './IERC1155Internal.sol'; import { IERC165 } from '../../introspection/IERC165.sol'; /** * @title ERC1155 interface * @dev see https://github.com/ethereum/EIPs/issues/1155 */ interface IERC1155 is IERC1155Internal, IERC165 { /** * @notice query the balance of given token held by given address * @param account address to query * @param id token to query * @return token balance */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @notice query the balances of given tokens held by given addresses * @param accounts addresss to query * @param ids tokens to query * @return token balances */ function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory); /** * @notice query approval status of given operator with respect to given address * @param account address to query for approval granted * @param operator address to query for approval received * @return whether operator is approved to spend tokens held by account */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @notice grant approval to or revoke approval from given operator to spend held tokens * @param operator address whose approval status to update * @param status whether operator should be considered approved */ function setApprovalForAll(address operator, bool status) external; /** * @notice transfer tokens between given addresses, checking for ERC1155Receiver implementation if applicable * @param from sender of tokens * @param to receiver of tokens * @param id token ID * @param amount quantity of tokens to transfer * @param data data payload */ function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @notice transfer batch of tokens between given addresses, checking for ERC1155Receiver implementation if applicable * @param from sender of tokens * @param to receiver of tokens * @param ids list of token IDs * @param amounts list of quantities of tokens to transfer * @param data data payload */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC20Internal } from './IERC20Internal.sol'; /** * @title ERC20 interface * @dev see https://github.com/ethereum/EIPs/issues/20 */ interface IERC20 is IERC20Internal { /** * @notice query the total minted token supply * @return token supply */ function totalSupply() external view returns (uint256); /** * @notice query the token balance of given account * @param account address to query * @return token balance */ function balanceOf(address account) external view returns (uint256); /** * @notice query the allowance granted from given holder to given spender * @param holder approver of allowance * @param spender recipient of allowance * @return token allowance */ function allowance(address holder, address spender) external view returns (uint256); /** * @notice grant approval to spender to spend tokens * @dev prefer ERC20Extended functions to avoid transaction-ordering vulnerability (see https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729) * @param spender recipient of allowance * @param amount quantity of tokens approved for spending * @return success status (always true; otherwise function should revert) */ function approve(address spender, uint256 amount) external returns (bool); /** * @notice transfer tokens to given recipient * @param recipient beneficiary of token transfer * @param amount quantity of tokens to transfer * @return success status (always true; otherwise function should revert) */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @notice transfer tokens to given recipient on behalf of given holder * @param holder holder of tokens prior to transfer * @param recipient beneficiary of token transfer * @param amount quantity of tokens to transfer * @return success status (always true; otherwise function should revert) */ function transferFrom( address holder, address recipient, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title ERC20 metadata interface */ interface IERC20Metadata { /** * @notice return token name * @return token name */ function name() external view returns (string memory); /** * @notice return token symbol * @return token symbol */ function symbol() external view returns (string memory); /** * @notice return token decimals, generally used only for display purposes * @return token decimals */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC20 } from '../token/ERC20/IERC20.sol'; import { IERC20Metadata } from '../token/ERC20/metadata/IERC20Metadata.sol'; /** * @title WETH (Wrapped ETH) interface */ interface IWETH is IERC20, IERC20Metadata { /** * @notice convert ETH to WETH */ function deposit() external payable; /** * @notice convert WETH to ETH * @dev if caller is a contract, it should have a fallback or receive function * @param amount quantity of WETH to convert, denominated in wei */ function withdraw(uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Helper library for safe casting of uint and int values * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license) */ library SafeCast { function toUint224(uint256 value) internal pure returns (uint224) { require(value <= type(uint224).max, 'SafeCast: value does not fit'); return uint224(value); } function toUint128(uint256 value) internal pure returns (uint128) { require(value <= type(uint128).max, 'SafeCast: value does not fit'); return uint128(value); } function toUint96(uint256 value) internal pure returns (uint96) { require(value <= type(uint96).max, 'SafeCast: value does not fit'); return uint96(value); } function toUint64(uint256 value) internal pure returns (uint64) { require(value <= type(uint64).max, 'SafeCast: value does not fit'); return uint64(value); } function toUint32(uint256 value) internal pure returns (uint32) { require(value <= type(uint32).max, 'SafeCast: value does not fit'); return uint32(value); } function toUint16(uint256 value) internal pure returns (uint16) { require(value <= type(uint16).max, 'SafeCast: value does not fit'); return uint16(value); } function toUint8(uint256 value) internal pure returns (uint8) { require(value <= type(uint8).max, 'SafeCast: value does not fit'); return uint8(value); } function toUint256(int256 value) internal pure returns (uint256) { require(value >= 0, 'SafeCast: value must be positive'); return uint256(value); } function toInt128(int256 value) internal pure returns (int128) { require( value >= type(int128).min && value <= type(int128).max, 'SafeCast: value does not fit' ); return int128(value); } function toInt64(int256 value) internal pure returns (int64) { require( value >= type(int64).min && value <= type(int64).max, 'SafeCast: value does not fit' ); return int64(value); } function toInt32(int256 value) internal pure returns (int32) { require( value >= type(int32).min && value <= type(int32).max, 'SafeCast: value does not fit' ); return int32(value); } function toInt16(int256 value) internal pure returns (int16) { require( value >= type(int16).min && value <= type(int16).max, 'SafeCast: value does not fit' ); return int16(value); } function toInt8(int256 value) internal pure returns (int8) { require( value >= type(int8).min && value <= type(int8).max, 'SafeCast: value does not fit' ); return int8(value); } function toInt256(uint256 value) internal pure returns (int256) { require( value <= uint256(type(int256).max), 'SafeCast: value does not fit' ); return int256(value); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC20 } from '../token/ERC20/IERC20.sol'; import { AddressUtils } from './AddressUtils.sol'; /** * @title Safe ERC20 interaction library * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license) */ library SafeERC20 { using AddressUtils for address; function safeTransfer( IERC20 token, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transfer.selector, to, value) ); } function safeTransferFrom( IERC20 token, address from, address to, uint256 value ) internal { _callOptionalReturn( token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value) ); } /** * @dev safeApprove (like approve) should only be called when setting an initial allowance or when resetting it to zero; otherwise prefer safeIncreaseAllowance and safeDecreaseAllowance */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { 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) ); } function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 newAllowance = token.allowance(address(this), spender) + value; _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } 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' ); uint256 newAllowance = oldAllowance - value; _callOptionalReturn( token, abi.encodeWithSelector( token.approve.selector, spender, newAllowance ) ); } } /** * @notice send transaction data and check validity of return value, if present * @param token ERC20 token interface * @param data transaction data */ function _callOptionalReturn(IERC20 token, bytes memory data) private { bytes memory returndata = address(token).functionCall( data, 'SafeERC20: low-level call failed' ); if (returndata.length > 0) { require( abi.decode(returndata, (bool)), 'SafeERC20: ERC20 operation did not succeed' ); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "abdk-libraries-solidity/ABDKMath64x64.sol"; import "@solidstate/abdk-math-extensions/contracts/ABDKMath64x64Token.sol"; /** * @title Option Math Helper Library */ library OptionMath { using ABDKMath64x64 for int128; using ABDKMath64x64 for uint256; using ABDKMath64x64Token for int128; using ABDKMath64x64Token for uint256; int256 private constant ONE = 10000000000000000000; struct Value { int256 value; int256 ruler; } /** * @custom:author Yaojin Sun * @notice applies ceiling to the second highest place value of a positive 64x64 fixed point number * @param x 64x64 fixed point number * @return rounded 64x64 fixed point number */ function ceil64x64(int128 x) internal pure returns (int128) { require(x > 0); (int256 integer, Value[3] memory values) = _getPositivePlaceValues(x); // if the summation of first and second values is equal to integer, the integer has already been rounded if ( values[0].ruler * values[0].value + values[1].ruler * values[1].value == integer ) { return int128((integer << 64) / ONE); } return int128( (((values[0].ruler * values[0].value) + (values[1].ruler * (values[1].value + 1))) << 64) / ONE ); } /** * @custom:author Yaojin Sun * @notice applies floor to the second highest place value of a positive 64x64 fixed point number * @param x 64x64 fixed point number * @return rounded 64x64 fixed point number */ function floor64x64(int128 x) internal pure returns (int128) { require(x > 0); (, Value[3] memory values) = _getPositivePlaceValues(x); // No matter whether third value is non-zero or not, we ONLY need to keep the first and second places. int256 res = (values[0].ruler * values[0].value) + (values[1].ruler * values[1].value); return int128((res << 64) / ONE); } function _getPositivePlaceValues(int128 x) private pure returns (int256, Value[3] memory) { // move the decimal part to integer by multiplying 10...0 int256 integer = (int256(x) * ONE) >> 64; // scan and identify the highest position int256 ruler = 100000000000000000000000000000000000000; // 10^38 while (integer < ruler) { ruler = ruler / 10; } Value[3] memory values; // find the first/second/third largest places and there value values[0] = Value(0, 0); values[1] = Value(0, 0); values[2] = Value(0, 0); // setup the first place value values[0].ruler = ruler; if (values[0].ruler != 0) { values[0].value = (integer / values[0].ruler) % 10; // setup the second place value values[1].ruler = ruler / 10; if (values[1].ruler != 0) { values[1].value = (integer / values[1].ruler) % 10; // setup the third place value values[2].ruler = ruler / 100; if (values[2].ruler != 0) { values[2].value = (integer / values[2].ruler) % 10; } } } return (integer, values); } /** * @notice converts the value to the base token amount * @param underlyingDecimals decimal precision of the underlying asset * @param baseDecimals decimal precision of the base asset * @param value amount to convert * @return decimal representation of base token amount */ function toBaseTokenAmount( uint8 underlyingDecimals, uint8 baseDecimals, uint256 value ) internal pure returns (uint256) { int128 value64x64 = value.fromDecimals(underlyingDecimals); return value64x64.toDecimals(baseDecimals); } /** * @notice calculates the collateral asset amount from the number of contracts * @param isCall option type, true if call option * @param underlyingDecimals decimal precision of the underlying asset * @param baseDecimals decimal precision of the base asset * @param strike64x64 strike price of the option as 64x64 fixed point number * @return collateral asset amount */ function fromContractsToCollateral( uint256 contracts, bool isCall, uint8 underlyingDecimals, uint8 baseDecimals, int128 strike64x64 ) internal pure returns (uint256) { if (strike64x64 == 0) { return 0; } if (isCall) { return contracts; } return toBaseTokenAmount( underlyingDecimals, baseDecimals, strike64x64.mulu(contracts) ); } /** * @notice calculates number of contracts from the collateral asset amount * @param isCall option type, true if call option * @param baseDecimals decimal precision of the base asset * @param strike64x64 strike price of the option as 64x64 fixed point number * @return number of contracts */ function fromCollateralToContracts( uint256 collateral, bool isCall, uint8 baseDecimals, int128 strike64x64 ) internal pure returns (uint256) { if (strike64x64 == 0) { return 0; } if (isCall) { return collateral; } int128 collateral64x64 = collateral.fromDecimals(baseDecimals); return collateral64x64.div(strike64x64).toDecimals(baseDecimals); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IPremiaPool { struct PoolSettings { address underlying; address base; address underlyingOracle; address baseOracle; } /** * @notice query holders of given token * @param id token id to query * @return list of holder addresses */ function accountsByToken(uint256 id) external view returns (address[] memory); /** * @notice query the balance of given token held by given address * @param account address to query * @param id token to query * @return token balance */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @notice exercise option on behalf of holder * @param holder owner of long option tokens to exercise * @param longTokenId long option token id * @param contractSize quantity of tokens to exercise */ function exerciseFrom( address holder, uint256 longTokenId, uint256 contractSize ) external; /** * @notice get fundamental pool attributes * @return structured PoolSettings */ function getPoolSettings() external view returns (PoolSettings memory); /** * @notice get first oracle price update after timestamp. If no update has been registered yet, * return current price feed spot price * @param timestamp timestamp to query * @return spot64x64 64x64 fixed point representation of price */ function getPriceAfter64x64(uint256 timestamp) external view returns (int128 spot64x64); /** * @notice process expired option, freeing liquidity and distributing profits * @param longTokenId long option token id * @param contractSize quantity of tokens to process */ function processExpired(uint256 longTokenId, uint256 contractSize) external; function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) external; /** * @notice set timestamp after which reinvestment is disabled * @param timestamp timestamp to begin divestment * @param isCallPool whether we set divestment timestamp for the call pool or put pool */ function setDivestmentTimestamp(uint64 timestamp, bool isCallPool) external; /** * @notice query tokens held by given address * @param account address to query * @return list of token ids */ function tokensByAccount(address account) external view returns (uint256[] memory); /** * @notice force update of oracle price and pending deposit pool */ function update() external; /** * @notice redeem pool share tokens for underlying asset * @param amount quantity of share tokens to redeem * @param isCallPool whether to deposit underlying in the call pool or base in the put pool */ function withdraw(uint256 amount, bool isCallPool) external; /** * @notice write option without using liquidity from the pool on behalf of another address * @param underwriter underwriter of the option from who collateral will be deposited * @param longReceiver address who will receive the long token (Can be the underwriter) * @param maturity timestamp of option maturity * @param strike64x64 64x64 fixed point representation of strike price * @param contractSize quantity of option contract tokens to write * @param isCall whether this is a call or a put * @return longTokenId token id of the long call * @return shortTokenId token id of the short option */ function writeFrom( address underwriter, address longReceiver, uint64 maturity, int128 strike64x64, uint256 contractSize, bool isCall ) external payable returns (uint256 longTokenId, uint256 shortTokenId); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../vendor/IPremiaPool.sol"; import "./IVaultAdmin.sol"; import "./IVaultBase.sol"; import "./IVaultEvents.sol"; import "./IVaultView.sol"; /** * @title Knox Vault Interface */ interface IVault is IVaultAdmin, IVaultBase, IVaultEvents, IVaultView { /** * @notice gets the collateral asset ERC20 interface * @return ERC20 interface */ function ERC20() external view returns (IERC20); /** * @notice gets the pool interface * @return pool interface */ function Pool() external view returns (IPremiaPool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@solidstate/contracts/utils/EnumerableSet.sol"; import "../pricer/IPricer.sol"; import "../vendor/IExchangeHelper.sol"; import "./OrderBook.sol"; /** * @title Knox Dutch Auction Diamond Storage Library */ library AuctionStorage { using OrderBook for OrderBook.Index; struct InitAuction { uint64 epoch; uint64 expiry; int128 strike64x64; uint256 longTokenId; uint256 startTime; uint256 endTime; } enum Status {UNINITIALIZED, INITIALIZED, FINALIZED, PROCESSED, CANCELLED} struct Auction { // status of the auction Status status; // option expiration timestamp uint64 expiry; // option strike price int128 strike64x64; // auction max price int128 maxPrice64x64; // auction min price int128 minPrice64x64; // last price paid during the auction int128 lastPrice64x64; // auction start timestamp uint256 startTime; // auction end timestamp uint256 endTime; // auction processed timestamp uint256 processedTime; // total contracts available uint256 totalContracts; // total contracts sold uint256 totalContractsSold; // total unclaimed contracts uint256 totalUnclaimedContracts; // total premiums collected uint256 totalPremiums; // option long token id uint256 longTokenId; } struct Layout { // percent offset from delta strike int128 deltaOffset64x64; // minimum order size uint256 minSize; // mapping of auctions to epoch id (epoch id -> auction) mapping(uint64 => Auction) auctions; // mapping of order books to epoch id (epoch id -> order book) mapping(uint64 => OrderBook.Index) orderbooks; // mapping of unique order ids (uoids) to buyer addresses (buyer -> uoid) mapping(address => EnumerableSet.UintSet) uoids; // ExchangeHelper contract interface IExchangeHelper Exchange; // Pricer contract interface IPricer Pricer; } bytes32 internal constant STORAGE_SLOT = keccak256("knox.contracts.storage.Auction"); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } /************************************************ * VIEW ***********************************************/ /** * @notice returns the auction parameters * @param epoch epoch id * @return auction parameters */ function _getAuction(uint64 epoch) internal view returns (Auction memory) { return layout().auctions[epoch]; } /** * @notice returns percent delta offset * @return percent delta offset as a 64x64 fixed point number */ function _getDeltaOffset64x64() internal view returns (int128) { return layout().deltaOffset64x64; } /** * @notice returns the minimum order size * @return minimum order size */ function _getMinSize() internal view returns (uint256) { return layout().minSize; } /** * @notice returns the order from the auction orderbook * @param epoch epoch id * @param orderId order id * @return order from auction orderbook */ function _getOrderById(uint64 epoch, uint128 orderId) internal view returns (OrderBook.Data memory) { OrderBook.Index storage orderbook = layout().orderbooks[epoch]; return orderbook._getOrderById(orderId); } /** * @notice returns the status of the auction * @param epoch epoch id * @return auction status */ function _getStatus(uint64 epoch) internal view returns (AuctionStorage.Status) { return layout().auctions[epoch].status; } /** * @notice returns the stored total number of contracts that can be sold during the auction * returns 0 if the auction has not started * @param epoch epoch id * @return total number of contracts which may be sold */ function _getTotalContracts(uint64 epoch) internal view returns (uint256) { return layout().auctions[epoch].totalContracts; } /** * @notice returns the total number of contracts sold * @param epoch epoch id * @return total number of contracts sold */ function _getTotalContractsSold(uint64 epoch) internal view returns (uint256) { return layout().auctions[epoch].totalContractsSold; } /************************************************ * HELPERS ***********************************************/ /** * @notice calculates the unique order id * @param epoch epoch id * @param orderId order id * @return unique order id */ function _formatUniqueOrderId(uint64 epoch, uint128 orderId) internal view returns (uint256) { // uses the first 8 bytes of the contract address to salt uoid bytes8 salt = bytes8(bytes20(address(this))); return (uint256(uint64(salt)) << 192) + (uint256(epoch) << 128) + uint256(orderId); } /** * @notice derives salt, epoch id, and order id from the unique order id * @param uoid unique order id * @return salt * @return epoch id * @return order id */ function _parseUniqueOrderId(uint256 uoid) internal pure returns ( bytes8, uint64, uint128 ) { uint64 salt; uint64 epoch; uint128 orderId; assembly { salt := shr(192, uoid) epoch := shr(128, uoid) orderId := uoid } return (bytes8(salt), epoch, orderId); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./AuctionStorage.sol"; /** * @title Knox Auction Events Interface */ interface IAuctionEvents { /** * @notice emitted when the auction max/min prices have been set * @param epoch epoch id * @param strike64x64 strike price as a 64x64 fixed point number * @param offsetStrike64x64 offset strike price as a 64x64 fixed point number * @param spot64x64 spot price as a 64x64 fixed point number * @param maxPrice64x64 max price as a 64x64 fixed point number * @param minPrice64x64 min price as a 64x64 fixed point number */ event AuctionPricesSet( uint64 indexed epoch, int128 strike64x64, int128 offsetStrike64x64, int128 spot64x64, int128 maxPrice64x64, int128 minPrice64x64 ); /** * @notice emitted when the exchange auction status is updated * @param epoch epoch id * @param status auction status */ event AuctionStatusSet(uint64 indexed epoch, AuctionStorage.Status status); /** * @notice emitted when the delta offset is updated * @param oldDeltaOffset previous delta offset * @param newDeltaOffset new delta offset * @param caller address of admin */ event DeltaOffsetSet( int128 oldDeltaOffset, int128 newDeltaOffset, address caller ); /** * @notice emitted when the exchange helper contract address is updated * @param oldExchangeHelper previous exchange helper address * @param newExchangeHelper new exchange helper address * @param caller address of admin */ event ExchangeHelperSet( address oldExchangeHelper, address newExchangeHelper, address caller ); /** * @notice emitted when an external function reverts * @param message error message */ event Log(string message); /** * @notice emitted when the minimum order size is updated * @param oldMinSize previous minimum order size * @param newMinSize new minimum order size * @param caller address of admin */ event MinSizeSet(uint256 oldMinSize, uint256 newMinSize, address caller); /** * @notice emitted when a market or limit order has been placed * @param epoch epoch id * @param orderId order id * @param buyer address of buyer * @param price64x64 price paid as a 64x64 fixed point number * @param size quantity of options purchased * @param isLimitOrder true if order is a limit order */ event OrderAdded( uint64 indexed epoch, uint128 orderId, address buyer, int128 price64x64, uint256 size, bool isLimitOrder ); /** * @notice emitted when a limit order has been cancelled * @param epoch epoch id * @param orderId order id * @param buyer address of buyer */ event OrderCanceled(uint64 indexed epoch, uint128 orderId, address buyer); /** * @notice emitted when an order (filled or unfilled) is withdrawn * @param epoch epoch id * @param buyer address of buyer * @param refund amount sent back to the buyer as a result of an overpayment * @param fill amount in long token contracts sent to the buyer */ event OrderWithdrawn( uint64 indexed epoch, address buyer, uint256 refund, uint256 fill ); /** * @notice emitted when the pricer contract address is updated * @param oldPricer previous pricer address * @param newPricer new pricer address * @param caller address of admin */ event PricerSet(address oldPricer, address newPricer, address caller); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC173Internal } from '../IERC173Internal.sol'; interface IOwnableInternal is IERC173Internal {}
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; library OwnableStorage { struct Layout { address owner; } bytes32 internal constant STORAGE_SLOT = keccak256('solidstate.contracts.storage.Ownable'); function layout() internal pure returns (Layout storage l) { bytes32 slot = STORAGE_SLOT; assembly { l.slot := slot } } function setOwner(Layout storage l, address owner) internal { l.owner = owner; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Partial ERC173 interface needed by internal functions */ interface IERC173Internal { event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC165 } from '../../introspection/IERC165.sol'; /** * @title Partial ERC1155 interface needed by internal functions */ interface IERC1155Internal { event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value ); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); event ApprovalForAll( address indexed account, address indexed operator, bool approved ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title ERC165 interface registration interface * @dev see https://eips.ethereum.org/EIPS/eip-165 */ interface IERC165 { /** * @notice query whether contract has registered support for given interface * @param interfaceId interface id * @return bool whether interface is supported */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Partial ERC20 interface needed by internal functions */ interface IERC20Internal { event Transfer(address indexed from, address indexed to, uint256 value); event Approval( address indexed owner, address indexed spender, uint256 value ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { UintUtils } from './UintUtils.sol'; library AddressUtils { using UintUtils for uint256; function toString(address account) internal pure returns (string memory) { return uint256(uint160(account)).toHexString(20); } function isContract(address account) internal view returns (bool) { uint256 size; assembly { size := extcodesize(account) } return size > 0; } function sendValue(address payable account, uint256 amount) internal { (bool success, ) = account.call{ value: amount }(''); require(success, 'AddressUtils: failed to send value'); } function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, 'AddressUtils: failed low-level call'); } function functionCall( address target, bytes memory data, string memory error ) internal returns (bytes memory) { return _functionCallWithValue(target, data, 0, error); } function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue( target, data, value, 'AddressUtils: failed low-level call with value' ); } function functionCallWithValue( address target, bytes memory data, uint256 value, string memory error ) internal returns (bytes memory) { require( address(this).balance >= value, 'AddressUtils: insufficient balance for call' ); return _functionCallWithValue(target, data, value, error); } function _functionCallWithValue( address target, bytes memory data, uint256 value, string memory error ) private returns (bytes memory) { require( isContract(target), 'AddressUtils: function call to non-contract' ); (bool success, bytes memory returnData) = target.call{ value: value }( data ); if (success) { return returnData; } else if (returnData.length > 0) { assembly { let returnData_size := mload(returnData) revert(add(32, returnData), returnData_size) } } else { revert(error); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title utility functions for uint256 operations * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license) */ library UintUtils { bytes16 private constant HEX_SYMBOLS = '0123456789abcdef'; function toString(uint256 value) internal pure returns (string memory) { if (value == 0) { return '0'; } uint256 temp = value; uint256 digits; while (temp != 0) { digits++; temp /= 10; } bytes memory buffer = new bytes(digits); while (value != 0) { digits -= 1; buffer[digits] = bytes1(uint8(48 + uint256(value % 10))); value /= 10; } return string(buffer); } function toHexString(uint256 value) internal pure returns (string memory) { if (value == 0) { return '0x00'; } uint256 length = 0; for (uint256 temp = value; temp != 0; temp >>= 8) { unchecked { length++; } } return toHexString(value, length); } function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = '0'; buffer[1] = 'x'; unchecked { for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_SYMBOLS[value & 0xf]; value >>= 4; } } require(value == 0, 'UintUtils: hex length insufficient'); return string(buffer); } }
// SPDX-License-Identifier: BSD-4-Clause /* * ABDK Math 64.64 Smart Contract Library. Copyright © 2019 by ABDK Consulting. * Author: Mikhail Vladimirov <[email protected]> */ pragma solidity ^0.8.0; /** * Smart contract library of mathematical functions operating with signed * 64.64-bit fixed point numbers. Signed 64.64-bit fixed point number is * basically a simple fraction whose numerator is signed 128-bit integer and * denominator is 2^64. As long as denominator is always the same, there is no * need to store it, thus in Solidity signed 64.64-bit fixed point numbers are * represented by int128 type holding only the numerator. */ library ABDKMath64x64 { /* * Minimum value signed 64.64-bit fixed point number may have. */ int128 private constant MIN_64x64 = -0x80000000000000000000000000000000; /* * Maximum value signed 64.64-bit fixed point number may have. */ int128 private constant MAX_64x64 = 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF; /** * Convert signed 256-bit integer number into signed 64.64-bit fixed point * number. Revert on overflow. * * @param x signed 256-bit integer number * @return signed 64.64-bit fixed point number */ function fromInt (int256 x) internal pure returns (int128) { unchecked { require (x >= -0x8000000000000000 && x <= 0x7FFFFFFFFFFFFFFF); return int128 (x << 64); } } /** * Convert signed 64.64 fixed point number into signed 64-bit integer number * rounding down. * * @param x signed 64.64-bit fixed point number * @return signed 64-bit integer number */ function toInt (int128 x) internal pure returns (int64) { unchecked { return int64 (x >> 64); } } /** * Convert unsigned 256-bit integer number into signed 64.64-bit fixed point * number. Revert on overflow. * * @param x unsigned 256-bit integer number * @return signed 64.64-bit fixed point number */ function fromUInt (uint256 x) internal pure returns (int128) { unchecked { require (x <= 0x7FFFFFFFFFFFFFFF); return int128 (int256 (x << 64)); } } /** * Convert signed 64.64 fixed point number into unsigned 64-bit integer * number rounding down. Revert on underflow. * * @param x signed 64.64-bit fixed point number * @return unsigned 64-bit integer number */ function toUInt (int128 x) internal pure returns (uint64) { unchecked { require (x >= 0); return uint64 (uint128 (x >> 64)); } } /** * Convert signed 128.128 fixed point number into signed 64.64-bit fixed point * number rounding down. Revert on overflow. * * @param x signed 128.128-bin fixed point number * @return signed 64.64-bit fixed point number */ function from128x128 (int256 x) internal pure returns (int128) { unchecked { int256 result = x >> 64; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Convert signed 64.64 fixed point number into signed 128.128 fixed point * number. * * @param x signed 64.64-bit fixed point number * @return signed 128.128 fixed point number */ function to128x128 (int128 x) internal pure returns (int256) { unchecked { return int256 (x) << 64; } } /** * Calculate x + y. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function add (int128 x, int128 y) internal pure returns (int128) { unchecked { int256 result = int256(x) + y; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate x - y. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function sub (int128 x, int128 y) internal pure returns (int128) { unchecked { int256 result = int256(x) - y; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate x * y rounding down. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function mul (int128 x, int128 y) internal pure returns (int128) { unchecked { int256 result = int256(x) * y >> 64; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate x * y rounding towards zero, where x is signed 64.64 fixed point * number and y is signed 256-bit integer number. Revert on overflow. * * @param x signed 64.64 fixed point number * @param y signed 256-bit integer number * @return signed 256-bit integer number */ function muli (int128 x, int256 y) internal pure returns (int256) { unchecked { if (x == MIN_64x64) { require (y >= -0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF && y <= 0x1000000000000000000000000000000000000000000000000); return -y << 63; } else { bool negativeResult = false; if (x < 0) { x = -x; negativeResult = true; } if (y < 0) { y = -y; // We rely on overflow behavior here negativeResult = !negativeResult; } uint256 absoluteResult = mulu (x, uint256 (y)); if (negativeResult) { require (absoluteResult <= 0x8000000000000000000000000000000000000000000000000000000000000000); return -int256 (absoluteResult); // We rely on overflow behavior here } else { require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int256 (absoluteResult); } } } } /** * Calculate x * y rounding down, where x is signed 64.64 fixed point number * and y is unsigned 256-bit integer number. Revert on overflow. * * @param x signed 64.64 fixed point number * @param y unsigned 256-bit integer number * @return unsigned 256-bit integer number */ function mulu (int128 x, uint256 y) internal pure returns (uint256) { unchecked { if (y == 0) return 0; require (x >= 0); uint256 lo = (uint256 (int256 (x)) * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)) >> 64; uint256 hi = uint256 (int256 (x)) * (y >> 128); require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); hi <<= 64; require (hi <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF - lo); return hi + lo; } } /** * Calculate x / y rounding towards zero. Revert on overflow or when y is * zero. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function div (int128 x, int128 y) internal pure returns (int128) { unchecked { require (y != 0); int256 result = (int256 (x) << 64) / y; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate x / y rounding towards zero, where x and y are signed 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x signed 256-bit integer number * @param y signed 256-bit integer number * @return signed 64.64-bit fixed point number */ function divi (int256 x, int256 y) internal pure returns (int128) { unchecked { require (y != 0); bool negativeResult = false; if (x < 0) { x = -x; // We rely on overflow behavior here negativeResult = true; } if (y < 0) { y = -y; // We rely on overflow behavior here negativeResult = !negativeResult; } uint128 absoluteResult = divuu (uint256 (x), uint256 (y)); if (negativeResult) { require (absoluteResult <= 0x80000000000000000000000000000000); return -int128 (absoluteResult); // We rely on overflow behavior here } else { require (absoluteResult <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return int128 (absoluteResult); // We rely on overflow behavior here } } } /** * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x unsigned 256-bit integer number * @param y unsigned 256-bit integer number * @return signed 64.64-bit fixed point number */ function divu (uint256 x, uint256 y) internal pure returns (int128) { unchecked { require (y != 0); uint128 result = divuu (x, y); require (result <= uint128 (MAX_64x64)); return int128 (result); } } /** * Calculate -x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function neg (int128 x) internal pure returns (int128) { unchecked { require (x != MIN_64x64); return -x; } } /** * Calculate |x|. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function abs (int128 x) internal pure returns (int128) { unchecked { require (x != MIN_64x64); return x < 0 ? -x : x; } } /** * Calculate 1 / x rounding towards zero. Revert on overflow or when x is * zero. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function inv (int128 x) internal pure returns (int128) { unchecked { require (x != 0); int256 result = int256 (0x100000000000000000000000000000000) / x; require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate arithmetics average of x and y, i.e. (x + y) / 2 rounding down. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function avg (int128 x, int128 y) internal pure returns (int128) { unchecked { return int128 ((int256 (x) + int256 (y)) >> 1); } } /** * Calculate geometric average of x and y, i.e. sqrt (x * y) rounding down. * Revert on overflow or in case x * y is negative. * * @param x signed 64.64-bit fixed point number * @param y signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function gavg (int128 x, int128 y) internal pure returns (int128) { unchecked { int256 m = int256 (x) * int256 (y); require (m >= 0); require (m < 0x4000000000000000000000000000000000000000000000000000000000000000); return int128 (sqrtu (uint256 (m))); } } /** * Calculate x^y assuming 0^0 is 1, where x is signed 64.64 fixed point number * and y is unsigned 256-bit integer number. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @param y uint256 value * @return signed 64.64-bit fixed point number */ function pow (int128 x, uint256 y) internal pure returns (int128) { unchecked { bool negative = x < 0 && y & 1 == 1; uint256 absX = uint128 (x < 0 ? -x : x); uint256 absResult; absResult = 0x100000000000000000000000000000000; if (absX <= 0x10000000000000000) { absX <<= 63; while (y != 0) { if (y & 0x1 != 0) { absResult = absResult * absX >> 127; } absX = absX * absX >> 127; if (y & 0x2 != 0) { absResult = absResult * absX >> 127; } absX = absX * absX >> 127; if (y & 0x4 != 0) { absResult = absResult * absX >> 127; } absX = absX * absX >> 127; if (y & 0x8 != 0) { absResult = absResult * absX >> 127; } absX = absX * absX >> 127; y >>= 4; } absResult >>= 64; } else { uint256 absXShift = 63; if (absX < 0x1000000000000000000000000) { absX <<= 32; absXShift -= 32; } if (absX < 0x10000000000000000000000000000) { absX <<= 16; absXShift -= 16; } if (absX < 0x1000000000000000000000000000000) { absX <<= 8; absXShift -= 8; } if (absX < 0x10000000000000000000000000000000) { absX <<= 4; absXShift -= 4; } if (absX < 0x40000000000000000000000000000000) { absX <<= 2; absXShift -= 2; } if (absX < 0x80000000000000000000000000000000) { absX <<= 1; absXShift -= 1; } uint256 resultShift = 0; while (y != 0) { require (absXShift < 64); if (y & 0x1 != 0) { absResult = absResult * absX >> 127; resultShift += absXShift; if (absResult > 0x100000000000000000000000000000000) { absResult >>= 1; resultShift += 1; } } absX = absX * absX >> 127; absXShift <<= 1; if (absX >= 0x100000000000000000000000000000000) { absX >>= 1; absXShift += 1; } y >>= 1; } require (resultShift < 64); absResult >>= 64 - resultShift; } int256 result = negative ? -int256 (absResult) : int256 (absResult); require (result >= MIN_64x64 && result <= MAX_64x64); return int128 (result); } } /** * Calculate sqrt (x) rounding down. Revert if x < 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function sqrt (int128 x) internal pure returns (int128) { unchecked { require (x >= 0); return int128 (sqrtu (uint256 (int256 (x)) << 64)); } } /** * Calculate binary logarithm of x. Revert if x <= 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function log_2 (int128 x) internal pure returns (int128) { unchecked { require (x > 0); int256 msb = 0; int256 xc = x; if (xc >= 0x10000000000000000) { xc >>= 64; msb += 64; } if (xc >= 0x100000000) { xc >>= 32; msb += 32; } if (xc >= 0x10000) { xc >>= 16; msb += 16; } if (xc >= 0x100) { xc >>= 8; msb += 8; } if (xc >= 0x10) { xc >>= 4; msb += 4; } if (xc >= 0x4) { xc >>= 2; msb += 2; } if (xc >= 0x2) msb += 1; // No need to shift xc anymore int256 result = msb - 64 << 64; uint256 ux = uint256 (int256 (x)) << uint256 (127 - msb); for (int256 bit = 0x8000000000000000; bit > 0; bit >>= 1) { ux *= ux; uint256 b = ux >> 255; ux >>= 127 + b; result += bit * int256 (b); } return int128 (result); } } /** * Calculate natural logarithm of x. Revert if x <= 0. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function ln (int128 x) internal pure returns (int128) { unchecked { require (x > 0); return int128 (int256 ( uint256 (int256 (log_2 (x))) * 0xB17217F7D1CF79ABC9E3B39803F2F6AF >> 128)); } } /** * Calculate binary exponent of x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function exp_2 (int128 x) internal pure returns (int128) { unchecked { require (x < 0x400000000000000000); // Overflow if (x < -0x400000000000000000) return 0; // Underflow uint256 result = 0x80000000000000000000000000000000; if (x & 0x8000000000000000 > 0) result = result * 0x16A09E667F3BCC908B2FB1366EA957D3E >> 128; if (x & 0x4000000000000000 > 0) result = result * 0x1306FE0A31B7152DE8D5A46305C85EDEC >> 128; if (x & 0x2000000000000000 > 0) result = result * 0x1172B83C7D517ADCDF7C8C50EB14A791F >> 128; if (x & 0x1000000000000000 > 0) result = result * 0x10B5586CF9890F6298B92B71842A98363 >> 128; if (x & 0x800000000000000 > 0) result = result * 0x1059B0D31585743AE7C548EB68CA417FD >> 128; if (x & 0x400000000000000 > 0) result = result * 0x102C9A3E778060EE6F7CACA4F7A29BDE8 >> 128; if (x & 0x200000000000000 > 0) result = result * 0x10163DA9FB33356D84A66AE336DCDFA3F >> 128; if (x & 0x100000000000000 > 0) result = result * 0x100B1AFA5ABCBED6129AB13EC11DC9543 >> 128; if (x & 0x80000000000000 > 0) result = result * 0x10058C86DA1C09EA1FF19D294CF2F679B >> 128; if (x & 0x40000000000000 > 0) result = result * 0x1002C605E2E8CEC506D21BFC89A23A00F >> 128; if (x & 0x20000000000000 > 0) result = result * 0x100162F3904051FA128BCA9C55C31E5DF >> 128; if (x & 0x10000000000000 > 0) result = result * 0x1000B175EFFDC76BA38E31671CA939725 >> 128; if (x & 0x8000000000000 > 0) result = result * 0x100058BA01FB9F96D6CACD4B180917C3D >> 128; if (x & 0x4000000000000 > 0) result = result * 0x10002C5CC37DA9491D0985C348C68E7B3 >> 128; if (x & 0x2000000000000 > 0) result = result * 0x1000162E525EE054754457D5995292026 >> 128; if (x & 0x1000000000000 > 0) result = result * 0x10000B17255775C040618BF4A4ADE83FC >> 128; if (x & 0x800000000000 > 0) result = result * 0x1000058B91B5BC9AE2EED81E9B7D4CFAB >> 128; if (x & 0x400000000000 > 0) result = result * 0x100002C5C89D5EC6CA4D7C8ACC017B7C9 >> 128; if (x & 0x200000000000 > 0) result = result * 0x10000162E43F4F831060E02D839A9D16D >> 128; if (x & 0x100000000000 > 0) result = result * 0x100000B1721BCFC99D9F890EA06911763 >> 128; if (x & 0x80000000000 > 0) result = result * 0x10000058B90CF1E6D97F9CA14DBCC1628 >> 128; if (x & 0x40000000000 > 0) result = result * 0x1000002C5C863B73F016468F6BAC5CA2B >> 128; if (x & 0x20000000000 > 0) result = result * 0x100000162E430E5A18F6119E3C02282A5 >> 128; if (x & 0x10000000000 > 0) result = result * 0x1000000B1721835514B86E6D96EFD1BFE >> 128; if (x & 0x8000000000 > 0) result = result * 0x100000058B90C0B48C6BE5DF846C5B2EF >> 128; if (x & 0x4000000000 > 0) result = result * 0x10000002C5C8601CC6B9E94213C72737A >> 128; if (x & 0x2000000000 > 0) result = result * 0x1000000162E42FFF037DF38AA2B219F06 >> 128; if (x & 0x1000000000 > 0) result = result * 0x10000000B17217FBA9C739AA5819F44F9 >> 128; if (x & 0x800000000 > 0) result = result * 0x1000000058B90BFCDEE5ACD3C1CEDC823 >> 128; if (x & 0x400000000 > 0) result = result * 0x100000002C5C85FE31F35A6A30DA1BE50 >> 128; if (x & 0x200000000 > 0) result = result * 0x10000000162E42FF0999CE3541B9FFFCF >> 128; if (x & 0x100000000 > 0) result = result * 0x100000000B17217F80F4EF5AADDA45554 >> 128; if (x & 0x80000000 > 0) result = result * 0x10000000058B90BFBF8479BD5A81B51AD >> 128; if (x & 0x40000000 > 0) result = result * 0x1000000002C5C85FDF84BD62AE30A74CC >> 128; if (x & 0x20000000 > 0) result = result * 0x100000000162E42FEFB2FED257559BDAA >> 128; if (x & 0x10000000 > 0) result = result * 0x1000000000B17217F7D5A7716BBA4A9AE >> 128; if (x & 0x8000000 > 0) result = result * 0x100000000058B90BFBE9DDBAC5E109CCE >> 128; if (x & 0x4000000 > 0) result = result * 0x10000000002C5C85FDF4B15DE6F17EB0D >> 128; if (x & 0x2000000 > 0) result = result * 0x1000000000162E42FEFA494F1478FDE05 >> 128; if (x & 0x1000000 > 0) result = result * 0x10000000000B17217F7D20CF927C8E94C >> 128; if (x & 0x800000 > 0) result = result * 0x1000000000058B90BFBE8F71CB4E4B33D >> 128; if (x & 0x400000 > 0) result = result * 0x100000000002C5C85FDF477B662B26945 >> 128; if (x & 0x200000 > 0) result = result * 0x10000000000162E42FEFA3AE53369388C >> 128; if (x & 0x100000 > 0) result = result * 0x100000000000B17217F7D1D351A389D40 >> 128; if (x & 0x80000 > 0) result = result * 0x10000000000058B90BFBE8E8B2D3D4EDE >> 128; if (x & 0x40000 > 0) result = result * 0x1000000000002C5C85FDF4741BEA6E77E >> 128; if (x & 0x20000 > 0) result = result * 0x100000000000162E42FEFA39FE95583C2 >> 128; if (x & 0x10000 > 0) result = result * 0x1000000000000B17217F7D1CFB72B45E1 >> 128; if (x & 0x8000 > 0) result = result * 0x100000000000058B90BFBE8E7CC35C3F0 >> 128; if (x & 0x4000 > 0) result = result * 0x10000000000002C5C85FDF473E242EA38 >> 128; if (x & 0x2000 > 0) result = result * 0x1000000000000162E42FEFA39F02B772C >> 128; if (x & 0x1000 > 0) result = result * 0x10000000000000B17217F7D1CF7D83C1A >> 128; if (x & 0x800 > 0) result = result * 0x1000000000000058B90BFBE8E7BDCBE2E >> 128; if (x & 0x400 > 0) result = result * 0x100000000000002C5C85FDF473DEA871F >> 128; if (x & 0x200 > 0) result = result * 0x10000000000000162E42FEFA39EF44D91 >> 128; if (x & 0x100 > 0) result = result * 0x100000000000000B17217F7D1CF79E949 >> 128; if (x & 0x80 > 0) result = result * 0x10000000000000058B90BFBE8E7BCE544 >> 128; if (x & 0x40 > 0) result = result * 0x1000000000000002C5C85FDF473DE6ECA >> 128; if (x & 0x20 > 0) result = result * 0x100000000000000162E42FEFA39EF366F >> 128; if (x & 0x10 > 0) result = result * 0x1000000000000000B17217F7D1CF79AFA >> 128; if (x & 0x8 > 0) result = result * 0x100000000000000058B90BFBE8E7BCD6D >> 128; if (x & 0x4 > 0) result = result * 0x10000000000000002C5C85FDF473DE6B2 >> 128; if (x & 0x2 > 0) result = result * 0x1000000000000000162E42FEFA39EF358 >> 128; if (x & 0x1 > 0) result = result * 0x10000000000000000B17217F7D1CF79AB >> 128; result >>= uint256 (int256 (63 - (x >> 64))); require (result <= uint256 (int256 (MAX_64x64))); return int128 (int256 (result)); } } /** * Calculate natural exponent of x. Revert on overflow. * * @param x signed 64.64-bit fixed point number * @return signed 64.64-bit fixed point number */ function exp (int128 x) internal pure returns (int128) { unchecked { require (x < 0x400000000000000000); // Overflow if (x < -0x400000000000000000) return 0; // Underflow return exp_2 ( int128 (int256 (x) * 0x171547652B82FE1777D0FFDA0D23A7D12 >> 128)); } } /** * Calculate x / y rounding towards zero, where x and y are unsigned 256-bit * integer numbers. Revert on overflow or when y is zero. * * @param x unsigned 256-bit integer number * @param y unsigned 256-bit integer number * @return unsigned 64.64-bit fixed point number */ function divuu (uint256 x, uint256 y) private pure returns (uint128) { unchecked { require (y != 0); uint256 result; if (x <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF) result = (x << 64) / y; else { uint256 msb = 192; uint256 xc = x >> 192; if (xc >= 0x100000000) { xc >>= 32; msb += 32; } if (xc >= 0x10000) { xc >>= 16; msb += 16; } if (xc >= 0x100) { xc >>= 8; msb += 8; } if (xc >= 0x10) { xc >>= 4; msb += 4; } if (xc >= 0x4) { xc >>= 2; msb += 2; } if (xc >= 0x2) msb += 1; // No need to shift xc anymore result = (x << 255 - msb) / ((y - 1 >> msb - 191) + 1); require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); uint256 hi = result * (y >> 128); uint256 lo = result * (y & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); uint256 xh = x >> 192; uint256 xl = x << 64; if (xl < lo) xh -= 1; xl -= lo; // We rely on overflow behavior here lo = hi << 128; if (xl < lo) xh -= 1; xl -= lo; // We rely on overflow behavior here assert (xh == hi >> 128); result += xl / y; } require (result <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF); return uint128 (result); } } /** * Calculate sqrt (x) rounding down, where x is unsigned 256-bit integer * number. * * @param x unsigned 256-bit integer number * @return unsigned 128-bit integer number */ function sqrtu (uint256 x) private pure returns (uint128) { unchecked { if (x == 0) return 0; else { uint256 xx = x; uint256 r = 1; if (xx >= 0x100000000000000000000000000000000) { xx >>= 128; r <<= 64; } if (xx >= 0x10000000000000000) { xx >>= 64; r <<= 32; } if (xx >= 0x100000000) { xx >>= 32; r <<= 16; } if (xx >= 0x10000) { xx >>= 16; r <<= 8; } if (xx >= 0x100) { xx >>= 8; r <<= 4; } if (xx >= 0x10) { xx >>= 4; r <<= 2; } if (xx >= 0x8) { r <<= 1; } r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; r = (r + x / r) >> 1; // Seven iterations should be enough uint256 r1 = x / r; return uint128 (r < r1 ? r : r1); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { ABDKMath64x64 } from 'abdk-libraries-solidity/ABDKMath64x64.sol'; /** * @title SolidState token extensions for ABDKMath64x64 library */ library ABDKMath64x64Token { using ABDKMath64x64 for int128; /** * @notice convert 64x64 fixed point representation of token amount to decimal * @param value64x64 64x64 fixed point representation of token amount * @param decimals token display decimals * @return value decimal representation of token amount */ function toDecimals(int128 value64x64, uint8 decimals) internal pure returns (uint256 value) { value = value64x64.mulu(10**decimals); } /** * @notice convert decimal representation of token amount to 64x64 fixed point * @param value decimal representation of token amount * @param decimals token display decimals * @return value64x64 64x64 fixed point representation of token amount */ function fromDecimals(uint256 value, uint8 decimals) internal pure returns (int128 value64x64) { value64x64 = ABDKMath64x64.divu(value, 10**decimals); } /** * @notice convert 64x64 fixed point representation of token amount to wei (18 decimals) * @param value64x64 64x64 fixed point representation of token amount * @return value wei representation of token amount */ function toWei(int128 value64x64) internal pure returns (uint256 value) { value = toDecimals(value64x64, 18); } /** * @notice convert wei representation (18 decimals) of token amount to 64x64 fixed point * @param value wei representation of token amount * @return value64x64 64x64 fixed point representation of token amount */ function fromWei(uint256 value) internal pure returns (int128 value64x64) { value64x64 = fromDecimals(value, 18); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./VaultStorage.sol"; /** * @title Knox Vault Admin Interface */ interface IVaultAdmin { /************************************************ * ADMIN ***********************************************/ /** * @notice sets the new auction * @dev the auction contract address must be set during the vault initialization * @param newAuction address of the new auction */ function setAuction(address newAuction) external; /** * @notice sets the start and end offsets for the auction * @param newStartOffset new start offset * @param newEndOffset new end offset */ function setAuctionWindowOffsets( uint256 newStartOffset, uint256 newEndOffset ) external; /** * @notice sets the option delta value * @param newDelta64x64 new option delta value as a 64x64 fixed point number */ function setDelta64x64(int128 newDelta64x64) external; /** * @notice sets the new fee recipient * @param newFeeRecipient address of the new fee recipient */ function setFeeRecipient(address newFeeRecipient) external; /** * @notice sets the new keeper * @param newKeeper address of the new keeper */ function setKeeper(address newKeeper) external; /** * @notice sets the new pricer * @dev the pricer contract address must be set during the vault initialization * @param newPricer address of the new pricer */ function setPricer(address newPricer) external; /** * @notice sets the new queue * @dev the queue contract address must be set during the vault initialization * @param newQueue address of the new queue */ function setQueue(address newQueue) external; /** * @notice sets the performance fee for the vault * @param newPerformanceFee64x64 performance fee as a 64x64 fixed point number */ function setPerformanceFee64x64(int128 newPerformanceFee64x64) external; /************************************************ * INITIALIZE AUCTION ***********************************************/ /** * @notice sets the option parameters which will be sold, then initializes the auction */ function initializeAuction() external; /************************************************ * INITIALIZE EPOCH ***********************************************/ /** * @notice collects performance fee from epoch income, processes the queued deposits, * increments the epoch id, then sets the auction prices * @dev it assumed that an auction has already been initialized */ function initializeEpoch() external; /************************************************ * PROCESS AUCTION ***********************************************/ /** * @notice processes the auction when it has been finalized or cancelled * @dev it assumed that an auction has already been initialized and the auction prices * have been set */ function processAuction() external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@solidstate/contracts/token/ERC20/metadata/IERC20Metadata.sol"; import "@solidstate/contracts/token/ERC4626/IERC4626.sol"; import "@solidstate/contracts/utils/IMulticall.sol"; /** * @title Knox Vault Base Interface * @dev includes ERC20Metadata and ERC4626 interfaces */ interface IVaultBase is IERC20Metadata, IERC4626, IMulticall { }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Knox Vault Events Interface */ interface IVaultEvents { /** * @notice emitted when the auction contract address is updated * @param epoch epoch id * @param oldAuction previous auction address * @param newAuction new auction address * @param caller address of admin */ event AuctionSet( uint64 indexed epoch, address oldAuction, address newAuction, address caller ); /** * @notice emitted when the is processed * @param epoch epoch id * @param totalCollateralUsed contracts sold, denominated in the collateral asset * @param totalContractsSold contracts sold during the auction * @param totalPremiums premiums earned during the auction */ event AuctionProcessed( uint64 indexed epoch, uint256 totalCollateralUsed, uint256 totalContractsSold, uint256 totalPremiums ); /** * @notice emitted when the auction offset window is updated * @param epoch epoch id * @param oldStartOffset previous start offset * @param newStartOffset new start offset * @param oldEndOffset previous end offset * @param newEndOffset new end offset * @param caller address of admin */ event AuctionWindowOffsetsSet( uint64 indexed epoch, uint256 oldStartOffset, uint256 newStartOffset, uint256 oldEndOffset, uint256 newEndOffset, address caller ); /** * @notice emitted when the option delta is updated * @param epoch epoch id * @param oldDelta previous option delta * @param newDelta new option delta * @param caller address of admin */ event DeltaSet( uint64 indexed epoch, int128 oldDelta, int128 newDelta, address caller ); /** * @notice emitted when a distribution is sent to a liquidity provider * @param epoch epoch id * @param collateralAmount quantity of collateral distributed to the receiver * @param shortContracts quantity of short contracts distributed to the receiver * @param receiver address of the receiver */ event DistributionSent( uint64 indexed epoch, uint256 collateralAmount, uint256 shortContracts, address receiver ); /** * @notice emitted when the fee recipient address is updated * @param epoch epoch id * @param oldFeeRecipient previous fee recipient address * @param newFeeRecipient new fee recipient address * @param caller address of admin */ event FeeRecipientSet( uint64 indexed epoch, address oldFeeRecipient, address newFeeRecipient, address caller ); /** * @notice emitted when the keeper address is updated * @param epoch epoch id * @param oldKeeper previous keeper address * @param newKeeper new keeper address * @param caller address of admin */ event KeeperSet( uint64 indexed epoch, address oldKeeper, address newKeeper, address caller ); /** * @notice emitted when an external function reverts * @param message error message */ event Log(string message); /** * @notice emitted when option parameters are set * @param epoch epoch id * @param expiry expiration timestamp * @param strike64x64 strike price as a 64x64 fixed point number * @param longTokenId long token id * @param shortTokenId short token id */ event OptionParametersSet( uint64 indexed epoch, uint64 expiry, int128 strike64x64, uint256 longTokenId, uint256 shortTokenId ); /** * @notice emitted when the performance fee is collected * @param epoch epoch id * @param gain amount earned during the epoch * @param loss amount lost during the epoch * @param feeInCollateral fee from net income, denominated in the collateral asset */ event PerformanceFeeCollected( uint64 indexed epoch, uint256 gain, uint256 loss, uint256 feeInCollateral ); /** * @notice emitted when the performance fee is updated * @param epoch epoch id * @param oldPerformanceFee previous performance fee * @param newPerformanceFee new performance fee * @param caller address of admin */ event PerformanceFeeSet( uint64 indexed epoch, int128 oldPerformanceFee, int128 newPerformanceFee, address caller ); /** * @notice emitted when the pricer contract address is updated * @param epoch epoch id * @param oldPricer previous pricer address * @param newPricer new pricer address * @param caller address of admin */ event PricerSet( uint64 indexed epoch, address oldPricer, address newPricer, address caller ); /** * @notice emitted when the queue contract address is updated * @param epoch epoch id * @param oldQueue previous queue address * @param newQueue new queue address * @param caller address of admin */ event QueueSet( uint64 indexed epoch, address oldQueue, address newQueue, address caller ); /** * @notice emitted when the reserved liquidity is withdrawn from the pool * @param epoch epoch id * @param amount quantity of reserved liquidity removed from pool */ event ReservedLiquidityWithdrawn(uint64 indexed epoch, uint256 amount); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./VaultStorage.sol"; /** * @title Knox Vault View Interface */ interface IVaultView { /************************************************ * VIEW ***********************************************/ /** * @notice returns the address of assigned actors * @return address of owner * @return address of fee recipient * @return address of keeper */ function getActors() external view returns ( address, address, address ); /** * @notice returns the auction window offsets * @return start offset * @return end offset */ function getAuctionWindowOffsets() external view returns (uint256, uint256); /** * @notice returns the address of connected services * @return address of Auction * @return address of Premia Pool * @return address of Pricer * @return address of Queue */ function getConnections() external view returns ( address, address, address, address ); /** * @notice returns option delta * @return option delta as a 64x64 fixed point number */ function getDelta64x64() external view returns (int128); /** * @notice returns the current epoch * @return current epoch id */ function getEpoch() external view returns (uint64); /** * @notice returns the option by epoch id * @return option parameters */ function getOption(uint64 epoch) external view returns (VaultStorage.Option memory); /** * @notice returns option type (call/put) * @return true if opton is a call */ function getOptionType() external view returns (bool); /** * @notice returns performance fee * @return performance fee as a 64x64 fixed point number */ function getPerformanceFee64x64() external view returns (int128); /** * @notice returns the total amount of collateral and short contracts to distribute * @param assetAmount quantity of assets to withdraw * @return distribution amount in collateral asset * @return distribution amount in the short contracts */ function previewDistributions(uint256 assetAmount) external view returns (uint256, uint256); /** * @notice estimates the total reserved "active" collateral * @dev collateral is reserved from the auction to ensure the Vault has sufficent funds to * cover the APY fee * @return estimated amount of reserved "active" collateral */ function previewReserves() external view returns (uint256); /** * @notice estimates the total number of contracts from the collateral and reserves held by the vault * @param strike64x64 strike price of the option as 64x64 fixed point number * @param collateral amount of collateral held by vault * @param reserves amount of reserves held by vault * @return estimated number of contracts */ function previewTotalContracts( int128 strike64x64, uint256 collateral, uint256 reserves ) external view returns (uint256); /** * @notice calculates the total active vault by deducting the premiums from the ERC20 balance * @return total active collateral */ function totalCollateral() external view returns (uint256); /** * @notice calculates the short position value denominated in the collateral asset * @return total short position in collateral amount */ function totalShortAsCollateral() external view returns (uint256); /** * @notice returns the amount in short contracts underwitten by the vault * @return total short contracts */ function totalShortAsContracts() external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "../auction/IAuction.sol"; import "../pricer/IPricer.sol"; import "../queue/IQueue.sol"; /** * @title Knox Vault Diamond Storage Library */ library VaultStorage { struct InitProxy { bool isCall; int128 delta64x64; int128 reserveRate64x64; int128 performanceFee64x64; string name; string symbol; address keeper; address feeRecipient; address pricer; address pool; } struct InitImpl { address auction; address queue; address pricer; } struct Option { // option expiration timestamp uint64 expiry; // option strike price int128 strike64x64; // option long token id uint256 longTokenId; // option short token id uint256 shortTokenId; } struct Layout { // base asset decimals uint8 baseDecimals; // underlying asset decimals uint8 underlyingDecimals; // option type, true if option is a call bool isCall; // auction processing flag, true if auction has been processed bool auctionProcessed; // vault option delta int128 delta64x64; // mapping of options to epoch id (epoch id -> option) mapping(uint64 => Option) options; // epoch id uint64 epoch; // auction start offset in seconds (startOffset = startTime - expiry) uint256 startOffset; // auction end offset in seconds (endOffset = endTime - expiry) uint256 endOffset; // auction start timestamp uint256 startTime; // total asset amount withdrawn during an epoch uint256 totalWithdrawals; // total asset amount not including premiums collected from the auction uint256 lastTotalAssets; // total premium collected during the auction uint256 totalPremium; // performance fee collected during epoch initialization uint256 fee; // percentage of asset to be held as reserves int128 reserveRate64x64; // percentage of fees taken from net income int128 performanceFee64x64; // fee recipient address address feeRecipient; // keeper bot address address keeper; // Auction contract interface IAuction Auction; // Queue contract interface IQueue Queue; // Pricer contract interface IPricer Pricer; } bytes32 internal constant LAYOUT_SLOT = keccak256("knox.contracts.storage.Vault"); function layout() internal pure returns (Layout storage l) { bytes32 slot = LAYOUT_SLOT; assembly { l.slot := slot } } /************************************************ * VIEW ***********************************************/ /** * @notice returns the current epoch * @return current epoch id */ function _getEpoch() internal view returns (uint64) { return layout().epoch; } /** * @notice returns the option by epoch id * @return option parameters */ function _getOption(uint64 epoch) internal view returns (Option memory) { return layout().options[epoch]; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; /** * @title Knox Pricer Interface */ interface IPricer { /** * @notice gets the latest price of the underlying denominated in the base * @return price of underlying asset as 64x64 fixed point number */ function latestAnswer64x64() external view returns (int128); /** * @notice calculates the time remaining until maturity * @param expiry the expiry date as UNIX timestamp * @return time remaining until maturity */ function getTimeToMaturity64x64(uint64 expiry) external view returns (int128); /** * @notice gets the annualized volatility of the pool pair * @param spot64x64 spot price of the underlying as 64x64 fixed point number * @param strike64x64 strike price of the option as 64x64 fixed point number * @param timeToMaturity64x64 time remaining until maturity as a 64x64 fixed point number * @return annualized volatility as 64x64 fixed point number */ function getAnnualizedVolatility64x64( int128 spot64x64, int128 strike64x64, int128 timeToMaturity64x64 ) external view returns (int128); /** * @notice gets the option price using the Black-Scholes model * @param spot64x64 spot price of the underlying as 64x64 fixed point number * @param strike64x64 strike price of the option as 64x64 fixed point number * @param timeToMaturity64x64 time remaining until maturity as a 64x64 fixed point number * @param isCall option type, true if call option * @return price of the option denominated in the base as 64x64 fixed point number */ function getBlackScholesPrice64x64( int128 spot64x64, int128 strike64x64, int128 timeToMaturity64x64, bool isCall ) external view returns (int128); /** * @notice calculates the delta strike price * @param isCall option type, true if call option * @param expiry the expiry date as UNIX timestamp * @param delta64x64 option delta as 64x64 fixed point number * @return delta strike price as 64x64 fixed point number */ function getDeltaStrikePrice64x64( bool isCall, uint64 expiry, int128 delta64x64 ) external view returns (int128); /** * @notice rounds a value to the floor or ceiling depending on option type * @param isCall option type, true if call option * @param n input value * @return rounded value as 64x64 fixed point number */ function snapToGrid64x64(bool isCall, int128 n) external view returns (int128); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@solidstate/contracts/introspection/IERC165.sol"; import "@solidstate/contracts/token/ERC1155/IERC1155.sol"; import "@solidstate/contracts/token/ERC1155/enumerable/IERC1155Enumerable.sol"; import "@solidstate/contracts/utils/IMulticall.sol"; import "../vendor/IExchangeHelper.sol"; import "./IQueueEvents.sol"; /** * @title Knox Queue Interface */ interface IQueue is IERC165, IERC1155, IERC1155Enumerable, IMulticall, IQueueEvents { /************************************************ * ADMIN ***********************************************/ /** * @notice sets a new max TVL for deposits * @param newMaxTVL is the new TVL limit for deposits */ function setMaxTVL(uint256 newMaxTVL) external; /** * @notice sets a new Exchange Helper contract * @param newExchangeHelper is the new Exchange Helper contract address */ function setExchangeHelper(address newExchangeHelper) external; /************************************************ * DEPOSIT ***********************************************/ /** * @notice deposits collateral asset * @dev sent ETH will be wrapped as wETH, sender must approve contract * @param amount total collateral deposited */ function deposit(uint256 amount) external payable; /** * @notice swaps into the collateral asset and deposits the proceeds * @dev sent ETH will be wrapped as wETH, sender must approve contract * @param s swap arguments */ function swapAndDeposit(IExchangeHelper.SwapArgs calldata s) external payable; /************************************************ * CANCEL ***********************************************/ /** * @notice cancels deposit, refunds collateral asset * @dev cancellation must be made within the same epoch as the deposit * @param amount total collateral which will be withdrawn */ function cancel(uint256 amount) external; /************************************************ * REDEEM ***********************************************/ /** * @notice exchanges claim token for vault shares * @param tokenId claim token id */ function redeem(uint256 tokenId) external; /** * @notice exchanges claim token for vault shares * @param tokenId claim token id * @param receiver vault share recipient */ function redeem(uint256 tokenId, address receiver) external; /** * @notice exchanges claim token for vault shares * @param tokenId claim token id * @param receiver vault share recipient * @param owner claim token holder */ function redeem( uint256 tokenId, address receiver, address owner ) external; /** * @notice exchanges all claim tokens for vault shares */ function redeemMax() external; /** * @notice exchanges all claim tokens for vault shares * @param receiver vault share recipient */ function redeemMax(address receiver) external; /** * @notice exchanges all claim tokens for vault shares * @param receiver vault share recipient * @param owner claim token holder */ function redeemMax(address receiver, address owner) external; /************************************************ * INITIALIZE EPOCH ***********************************************/ /** * @notice transfers deposited collateral to vault, calculates the price per share */ function processDeposits() external; /************************************************ * VIEW ***********************************************/ /** * @notice returns the current claim token id * @return claim token id */ function getCurrentTokenId() external view returns (uint256); /** * @notice returns the current epoch of the queue * @return epoch id */ function getEpoch() external view returns (uint64); /** * @notice returns the max total value locked of the vault * @return max total value */ function getMaxTVL() external view returns (uint256); /** * @notice returns the price per share for a given claim token id * @param tokenId claim token id * @return price per share */ function getPricePerShare(uint256 tokenId) external view returns (uint256); /** * @notice returns unredeemed vault shares available for a given claim token * @param tokenId claim token id * @return unredeemed vault share amount */ function previewUnredeemed(uint256 tokenId) external view returns (uint256); /** * @notice returns unredeemed vault shares available for a given claim token * @param tokenId claim token id * @param owner claim token holder * @return unredeemed vault share amount */ function previewUnredeemed(uint256 tokenId, address owner) external view returns (uint256); /** * @notice returns unredeemed vault shares available for all claim tokens * @param owner claim token holder * @return unredeemed vault share amount */ function previewMaxUnredeemed(address owner) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC165 } from '../../introspection/IERC165.sol'; /** * @title ERC1155 transfer receiver interface */ interface IERC1155Receiver is IERC165 { /** * @notice validate receipt of ERC1155 transfer * @param operator executor of transfer * @param from sender of tokens * @param id token ID received * @param value quantity of tokens received * @param data data payload * @return function's own selector if transfer is accepted */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @notice validate receipt of ERC1155 batch transfer * @param operator executor of transfer * @param from sender of tokens * @param ids token IDs received * @param values quantities of tokens received * @param data data payload * @return function's own selector if transfer is accepted */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: LGPL-3.0-or-later pragma solidity ^0.8.0; /** * @title Premia Exchange Helper * @dev deployed standalone and referenced by internal functions * @dev do NOT set approval to this contract! */ interface IExchangeHelper { struct SwapArgs { // token to pass in to swap address tokenIn; // amount of tokenIn to trade uint256 amountInMax; //min amount out to be used to purchase uint256 amountOutMin; // exchange address to call to execute the trade address callee; // address for which to set allowance for the trade address allowanceTarget; // data to execute the trade bytes data; // address to which refund excess tokens address refundAddress; } /** * @notice perform arbitrary swap transaction * @param sourceToken source token to pull into this address * @param targetToken target token to buy * @param pullAmount amount of source token to start the trade * @param callee exchange address to call to execute the trade. * @param allowanceTarget address for which to set allowance for the trade * @param data calldata to execute the trade * @param refundAddress address that un-used source token goes to * @return amountOut quantity of targetToken yielded by swap */ function swapWithToken( address sourceToken, address targetToken, uint256 pullAmount, address callee, address allowanceTarget, bytes calldata data, address refundAddress ) external returns (uint256 amountOut); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Set implementation with enumeration functions * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts (MIT license) */ library EnumerableSet { struct Set { bytes32[] _values; // 1-indexed to allow 0 to signify nonexistence mapping(bytes32 => uint256) _indexes; } struct Bytes32Set { Set _inner; } struct AddressSet { Set _inner; } struct UintSet { Set _inner; } function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } function indexOf(Bytes32Set storage set, bytes32 value) internal view returns (uint256) { return _indexOf(set._inner, value); } function indexOf(AddressSet storage set, address value) internal view returns (uint256) { return _indexOf(set._inner, bytes32(uint256(uint160(value)))); } function indexOf(UintSet storage set, uint256 value) internal view returns (uint256) { return _indexOf(set._inner, bytes32(value)); } function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } function _at(Set storage set, uint256 index) private view returns (bytes32) { require( set._values.length > index, 'EnumerableSet: index out of bounds' ); return set._values[index]; } function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } function _indexOf(Set storage set, bytes32 value) private view returns (uint256) { unchecked { return set._indexes[value] - 1; } } function _length(Set storage set) private view returns (uint256) { return set._values.length; } function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); set._indexes[value] = set._values.length; return true; } else { return false; } } function _remove(Set storage set, bytes32 value) private returns (bool) { uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { unchecked { bytes32 last = set._values[set._values.length - 1]; // move last value to now-vacant index set._values[valueIndex - 1] = last; set._indexes[last] = valueIndex; } // clear last index set._values.pop(); delete set._indexes[value]; return true; } else { return false; } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Knox Auction Order Book Library * @dev based on PiperMerriam's Grove v0.3 * https://github.com/pipermerriam/ethereum-grove */ library OrderBook { struct Index { uint256 head; uint256 length; uint256 root; mapping(uint256 => Order) orders; } struct Order { Data data; uint256 parent; uint256 left; uint256 right; uint256 height; } struct Data { uint256 id; int128 price64x64; uint256 size; address buyer; } /// @dev Retrieve the highest bid in the order book. /// @param index The index that the order is part of. function _head(Index storage index) internal view returns (uint256) { return index.head; } /// @dev Retrieve the number of bids in the order book. /// @param index The index that the order is part of. function _length(Index storage index) internal view returns (uint256) { return index.length; } /// @dev Retrieve the id, price, size, and buyer for the order. /// @param index The index that the order is part of. /// @param id The id for the order to be looked up. function _getOrderById(Index storage index, uint256 id) internal view returns (Data memory) { return index.orders[id].data; } /// @dev Returns the previous bid in descending order. /// @param index The index that the order is part of. /// @param id The id for the order to be looked up. function _getPreviousOrder(Index storage index, uint256 id) internal view returns (uint256) { Order storage currentOrder = index.orders[id]; if (currentOrder.data.id == 0) { // Unknown order, just return 0; return 0; } Order memory child; if (currentOrder.left != 0) { // Trace left to latest child in left tree. child = index.orders[currentOrder.left]; while (child.right != 0) { child = index.orders[child.right]; } return child.data.id; } if (currentOrder.parent != 0) { // Now we trace back up through parent relationships, looking // for a link where the child is the right child of it's // parent. Order storage parent = index.orders[currentOrder.parent]; child = currentOrder; while (true) { if (parent.right == child.data.id) { return parent.data.id; } if (parent.parent == 0) { break; } child = parent; parent = index.orders[parent.parent]; } } // This is the first order, and has no previous order. return 0; } /// @dev Returns the next bid in descending order. /// @param index The index that the order is part of. /// @param id The id for the order to be looked up. function _getNextOrder(Index storage index, uint256 id) internal view returns (uint256) { Order storage currentOrder = index.orders[id]; if (currentOrder.data.id == 0) { // Unknown order, just return 0; return 0; } Order memory child; if (currentOrder.right != 0) { // Trace right to earliest child in right tree. child = index.orders[currentOrder.right]; while (child.left != 0) { child = index.orders[child.left]; } return child.data.id; } if (currentOrder.parent != 0) { // if the order is the left child of it's parent, then the // parent is the next one. Order storage parent = index.orders[currentOrder.parent]; child = currentOrder; while (true) { if (parent.left == child.data.id) { return parent.data.id; } if (parent.parent == 0) { break; } child = parent; parent = index.orders[parent.parent]; } // Now we need to trace all the way up checking to see if any parent is the } // This is the final order. return 0; } /// @dev Updates or Inserts the id into the index at its appropriate location based on the price provided. /// @param index The index that the order is part of. // / @param id The unique identifier of the data element the index order will represent. /// @param price64x64 The unit price specified by the buyer. /// @param size The size specified by the buyer. /// @param buyer The buyers wallet address. function _insert( Index storage index, int128 price64x64, uint256 size, address buyer ) internal returns (uint256) { index.length = index.length + 1; uint256 id = index.length; Data memory data = _getOrderById(index, index.head); int128 highestPricePaid = data.price64x64; if (index.head == 0 || price64x64 > highestPricePaid) { index.head = id; } if (index.orders[id].data.id == id) { // A order with this id already exists. If the price is // the same, then just return early, otherwise, remove it // and reinsert it. if (index.orders[id].data.price64x64 == price64x64) { return id; } _remove(index, id); } uint256 previousOrderId = 0; if (index.root == 0) { index.root = id; } Order storage currentOrder = index.orders[index.root]; // Do insertion while (true) { if (currentOrder.data.id == 0) { // This is a new unpopulated order. currentOrder.data.id = id; currentOrder.parent = previousOrderId; currentOrder.data.price64x64 = price64x64; currentOrder.data.size = size; currentOrder.data.buyer = buyer; break; } // Set the previous order id. previousOrderId = currentOrder.data.id; // The new order belongs in the right subtree if (price64x64 <= currentOrder.data.price64x64) { if (currentOrder.right == 0) { currentOrder.right = id; } currentOrder = index.orders[currentOrder.right]; continue; } // The new order belongs in the left subtree. if (currentOrder.left == 0) { currentOrder.left = id; } currentOrder = index.orders[currentOrder.left]; } // Rebalance the tree _rebalanceTree(index, currentOrder.data.id); return id; } /// @dev Remove the order for the given unique identifier from the index. /// @param index The index that should be removed /// @param id The unique identifier of the data element to remove. function _remove(Index storage index, uint256 id) internal returns (bool) { if (id == index.head) { index.head = _getNextOrder(index, id); } Order storage replacementOrder; Order storage parent; Order storage child; uint256 rebalanceOrigin; Order storage orderToDelete = index.orders[id]; if (orderToDelete.data.id != id) { // The id does not exist in the tree. return false; } if (orderToDelete.left != 0 || orderToDelete.right != 0) { // This order is not a leaf order and thus must replace itself in // it's tree by either the previous or next order. if (orderToDelete.left != 0) { // This order is guaranteed to not have a right child. replacementOrder = index.orders[ _getPreviousOrder(index, orderToDelete.data.id) ]; } else { // This order is guaranteed to not have a left child. replacementOrder = index.orders[ _getNextOrder(index, orderToDelete.data.id) ]; } // The replacementOrder is guaranteed to have a parent. parent = index.orders[replacementOrder.parent]; // Keep note of the location that our tree rebalancing should // start at. rebalanceOrigin = replacementOrder.data.id; // Join the parent of the replacement order with any subtree of // the replacement order. We can guarantee that the replacement // order has at most one subtree because of how getNextOrder and // getPreviousOrder are used. if (parent.left == replacementOrder.data.id) { parent.left = replacementOrder.right; if (replacementOrder.right != 0) { child = index.orders[replacementOrder.right]; child.parent = parent.data.id; } } if (parent.right == replacementOrder.data.id) { parent.right = replacementOrder.left; if (replacementOrder.left != 0) { child = index.orders[replacementOrder.left]; child.parent = parent.data.id; } } // Now we replace the orderToDelete with the replacementOrder. // This includes parent/child relationships for all of the // parent, the left child, and the right child. replacementOrder.parent = orderToDelete.parent; if (orderToDelete.parent != 0) { parent = index.orders[orderToDelete.parent]; if (parent.left == orderToDelete.data.id) { parent.left = replacementOrder.data.id; } if (parent.right == orderToDelete.data.id) { parent.right = replacementOrder.data.id; } } else { // If the order we are deleting is the root order update the // index root order pointer. index.root = replacementOrder.data.id; } replacementOrder.left = orderToDelete.left; if (orderToDelete.left != 0) { child = index.orders[orderToDelete.left]; child.parent = replacementOrder.data.id; } replacementOrder.right = orderToDelete.right; if (orderToDelete.right != 0) { child = index.orders[orderToDelete.right]; child.parent = replacementOrder.data.id; } } else if (orderToDelete.parent != 0) { // The order being deleted is a leaf order so we only erase it's // parent linkage. parent = index.orders[orderToDelete.parent]; if (parent.left == orderToDelete.data.id) { parent.left = 0; } if (parent.right == orderToDelete.data.id) { parent.right = 0; } // keep note of where the rebalancing should begin. rebalanceOrigin = parent.data.id; } else { // This is both a leaf order and the root order, so we need to // unset the root order pointer. index.root = 0; } // Now we zero out all of the fields on the orderToDelete. orderToDelete.data.id = 0; orderToDelete.data.price64x64 = 0; orderToDelete.data.size = 0; orderToDelete.data.buyer = 0x0000000000000000000000000000000000000000; orderToDelete.parent = 0; orderToDelete.left = 0; orderToDelete.right = 0; orderToDelete.height = 0; // Walk back up the tree rebalancing if (rebalanceOrigin != 0) { _rebalanceTree(index, rebalanceOrigin); } return true; } function _rebalanceTree(Index storage index, uint256 id) private { // Trace back up rebalancing the tree and updating heights as // needed.. Order storage currentOrder = index.orders[id]; while (true) { int256 balanceFactor = _getBalanceFactor(index, currentOrder.data.id); if (balanceFactor == 2) { // Right rotation (tree is heavy on the left) if (_getBalanceFactor(index, currentOrder.left) == -1) { // The subtree is leaning right so it need to be // rotated left before the current order is rotated // right. _rotateLeft(index, currentOrder.left); } _rotateRight(index, currentOrder.data.id); } if (balanceFactor == -2) { // Left rotation (tree is heavy on the right) if (_getBalanceFactor(index, currentOrder.right) == 1) { // The subtree is leaning left so it need to be // rotated right before the current order is rotated // left. _rotateRight(index, currentOrder.right); } _rotateLeft(index, currentOrder.data.id); } if ((-1 <= balanceFactor) && (balanceFactor <= 1)) { _updateOrderHeight(index, currentOrder.data.id); } if (currentOrder.parent == 0) { // Reached the root which may be new due to tree // rotation, so set it as the root and then break. break; } currentOrder = index.orders[currentOrder.parent]; } } function _getBalanceFactor(Index storage index, uint256 id) private view returns (int256) { Order storage order = index.orders[id]; return int256(index.orders[order.left].height) - int256(index.orders[order.right].height); } function _updateOrderHeight(Index storage index, uint256 id) private { Order storage order = index.orders[id]; order.height = _max( index.orders[order.left].height, index.orders[order.right].height ) + 1; } function _max(uint256 a, uint256 b) private pure returns (uint256) { if (a >= b) { return a; } return b; } function _rotateLeft(Index storage index, uint256 id) private { Order storage originalRoot = index.orders[id]; if (originalRoot.right == 0) { // Cannot rotate left if there is no right originalRoot to rotate into // place. revert(); } // The right child is the new root, so it gets the original // `originalRoot.parent` as it's parent. Order storage newRoot = index.orders[originalRoot.right]; newRoot.parent = originalRoot.parent; // The original root needs to have it's right child nulled out. originalRoot.right = 0; if (originalRoot.parent != 0) { // If there is a parent order, it needs to now point downward at // the newRoot which is rotating into the place where `order` was. Order storage parent = index.orders[originalRoot.parent]; // figure out if we're a left or right child and have the // parent point to the new order. if (parent.left == originalRoot.data.id) { parent.left = newRoot.data.id; } if (parent.right == originalRoot.data.id) { parent.right = newRoot.data.id; } } if (newRoot.left != 0) { // If the new root had a left child, that moves to be the // new right child of the original root order Order storage leftChild = index.orders[newRoot.left]; originalRoot.right = leftChild.data.id; leftChild.parent = originalRoot.data.id; } // Update the newRoot's left order to point at the original order. originalRoot.parent = newRoot.data.id; newRoot.left = originalRoot.data.id; if (newRoot.parent == 0) { index.root = newRoot.data.id; } _updateOrderHeight(index, originalRoot.data.id); _updateOrderHeight(index, newRoot.data.id); } function _rotateRight(Index storage index, uint256 id) private { Order storage originalRoot = index.orders[id]; if (originalRoot.left == 0) { // Cannot rotate right if there is no left order to rotate into // place. revert(); } // The left child is taking the place of order, so we update it's // parent to be the original parent of the order. Order storage newRoot = index.orders[originalRoot.left]; newRoot.parent = originalRoot.parent; // Null out the originalRoot.left originalRoot.left = 0; if (originalRoot.parent != 0) { // If the order has a parent, update the correct child to point // at the newRoot now. Order storage parent = index.orders[originalRoot.parent]; if (parent.left == originalRoot.data.id) { parent.left = newRoot.data.id; } if (parent.right == originalRoot.data.id) { parent.right = newRoot.data.id; } } if (newRoot.right != 0) { Order storage rightChild = index.orders[newRoot.right]; originalRoot.left = newRoot.right; rightChild.parent = originalRoot.data.id; } // Update the new root's right order to point to the original order. originalRoot.parent = newRoot.data.id; newRoot.right = originalRoot.data.id; if (newRoot.parent == 0) { index.root = newRoot.data.id; } // Recompute heights. _updateOrderHeight(index, originalRoot.data.id); _updateOrderHeight(index, newRoot.data.id); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface AggregatorV3Interface { function decimals() external view returns (uint8); function description() external view returns (string memory); function version() external view returns (uint256); // getRoundData and latestRoundData should both raise "No data present" // if they do not have data to report, instead of returning unset values // which could be misinterpreted as actual reported values. function getRoundData(uint80 _roundId) external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); function latestRoundData() external view returns ( uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC1155Internal } from '../IERC1155Internal.sol'; /** * @title ERC1155 enumerable and aggregate function interface */ interface IERC1155Enumerable is IERC1155Internal { /** * @notice query total minted supply of given token * @param id token id to query * @return token supply */ function totalSupply(uint256 id) external view returns (uint256); /** * @notice query total number of holders for given token * @param id token id to query * @return quantity of holders */ function totalHolders(uint256 id) external view returns (uint256); /** * @notice query holders of given token * @param id token id to query * @return list of holder addresses */ function accountsByToken(uint256 id) external view returns (address[] memory); /** * @notice query tokens held by given address * @param account address to query * @return list of token ids */ function tokensByAccount(address account) external view returns (uint256[] memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Knox Queue Events Interface */ interface IQueueEvents { /** * @notice emitted when a deposit is cancelled * @param epoch epoch id * @param depositer address of depositer * @param amount quantity of collateral assets removed from queue */ event Cancel(uint64 indexed epoch, address depositer, uint256 amount); /** * @notice emitted when a deposit is made * @param epoch epoch id * @param depositer address of depositer * @param amount quantity of collateral assets added to queue */ event Deposit(uint64 indexed epoch, address depositer, uint256 amount); /** * @notice emitted when the exchange helper contract address is updated * @param oldExchangeHelper previous exchange helper address * @param newExchangeHelper new exchange helper address * @param caller address of admin */ event ExchangeHelperSet( address oldExchangeHelper, address newExchangeHelper, address caller ); /** * @notice emitted when the max TVL is updated * @param epoch epoch id * @param oldMaxTVL previous max TVL amount * @param newMaxTVL new max TVL amount * @param caller address of admin */ event MaxTVLSet( uint64 indexed epoch, uint256 oldMaxTVL, uint256 newMaxTVL, address caller ); /** * @notice emitted when vault shares are redeemed * @param epoch epoch id * @param receiver address of receiver * @param depositer address of depositer * @param shares quantity of vault shares sent to receiver */ event Redeem( uint64 indexed epoch, address receiver, address depositer, uint256 shares ); /** * @notice emitted when the queued deposits are processed * @param epoch epoch id * @param deposits quantity of collateral assets processed * @param pricePerShare vault price per share calculated * @param shares quantity of vault shares sent to queue contract * @param claimTokenSupply quantity of claim tokens in supply */ event ProcessQueuedDeposits( uint64 indexed epoch, uint256 deposits, uint256 pricePerShare, uint256 shares, uint256 claimTokenSupply ); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { IERC20 } from '../ERC20/IERC20.sol'; import { IERC4626Internal } from './IERC4626Internal.sol'; /** * @title ERC4626 interface * @dev see https://github.com/ethereum/EIPs/issues/4626 */ interface IERC4626 is IERC4626Internal, IERC20 { /** * @notice get the address of the base token used for vault accountin purposes * @return base token address */ function asset() external view returns (address); /** * @notice get the total quantity of the base asset currently managed by the vault * @return total managed asset amount */ function totalAssets() external view returns (uint256); /** * @notice calculate the quantity of shares received in exchange for a given quantity of assets, not accounting for slippage * @param assetAmount quantity of assets to convert * @return shareAmount quantity of shares calculated */ function convertToShares(uint256 assetAmount) external view returns (uint256 shareAmount); /** * @notice calculate the quantity of assets received in exchange for a given quantity of shares, not accounting for slippage * @param shareAmount quantity of shares to convert * @return assetAmount quantity of assets calculated */ function convertToAssets(uint256 shareAmount) external view returns (uint256 assetAmount); /** * @notice calculate the maximum quantity of base assets which may be deposited on behalf of given receiver * @param receiver recipient of shares resulting from deposit * @return maxAssets maximum asset deposit amount */ function maxDeposit(address receiver) external view returns (uint256 maxAssets); /** * @notice calculate the maximum quantity of shares which may be minted on behalf of given receiver * @param receiver recipient of shares resulting from deposit * @return maxShares maximum share mint amount */ function maxMint(address receiver) external view returns (uint256 maxShares); /** * @notice calculate the maximum quantity of base assets which may be withdrawn by given holder * @param owner holder of shares to be redeemed * @return maxAssets maximum asset mint amount */ function maxWithdraw(address owner) external view returns (uint256 maxAssets); /** * @notice calculate the maximum quantity of shares which may be redeemed by given holder * @param owner holder of shares to be redeemed * @return maxShares maximum share redeem amount */ function maxRedeem(address owner) external view returns (uint256 maxShares); /** * @notice simulate a deposit of given quantity of assets * @param assetAmount quantity of assets to deposit * @return shareAmount quantity of shares to mint */ function previewDeposit(uint256 assetAmount) external view returns (uint256 shareAmount); /** * @notice simulate a minting of given quantity of shares * @param shareAmount quantity of shares to mint * @return assetAmount quantity of assets to deposit */ function previewMint(uint256 shareAmount) external view returns (uint256 assetAmount); /** * @notice simulate a withdrawal of given quantity of assets * @param assetAmount quantity of assets to withdraw * @return shareAmount quantity of shares to redeem */ function previewWithdraw(uint256 assetAmount) external view returns (uint256 shareAmount); /** * @notice simulate a redemption of given quantity of shares * @param shareAmount quantity of shares to redeem * @return assetAmount quantity of assets to withdraw */ function previewRedeem(uint256 shareAmount) external view returns (uint256 assetAmount); /** * @notice execute a deposit of assets on behalf of given address * @param assetAmount quantity of assets to deposit * @param receiver recipient of shares resulting from deposit * @return shareAmount quantity of shares to mint */ function deposit(uint256 assetAmount, address receiver) external returns (uint256 shareAmount); /** * @notice execute a minting of shares on behalf of given address * @param shareAmount quantity of shares to mint * @param receiver recipient of shares resulting from deposit * @return assetAmount quantity of assets to deposit */ function mint(uint256 shareAmount, address receiver) external returns (uint256 assetAmount); /** * @notice execute a withdrawal of assets on behalf of given address * @param assetAmount quantity of assets to withdraw * @param receiver recipient of assets resulting from withdrawal * @param owner holder of shares to be redeemed * @return shareAmount quantity of shares to redeem */ function withdraw( uint256 assetAmount, address receiver, address owner ) external returns (uint256 shareAmount); /** * @notice execute a redemption of shares on behalf of given address * @param shareAmount quantity of shares to redeem * @param receiver recipient of assets resulting from withdrawal * @param owner holder of shares to be redeemed * @return assetAmount quantity of assets to withdraw */ function redeem( uint256 shareAmount, address receiver, address owner ) external returns (uint256 assetAmount); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @title Partial ERC4626 interface needed by internal functions */ interface IERC4626Internal { event Deposit( address indexed caller, address indexed owner, uint256 assets, uint256 shares ); event Withdraw( address indexed caller, address indexed receiver, address indexed owner, uint256 assets, uint256 shares ); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"bool","name":"isCall","type":"bool"},{"internalType":"address","name":"pool","type":"address"},{"internalType":"address","name":"vault","type":"address"},{"internalType":"address","name":"weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"epoch","type":"uint64"},{"indexed":false,"internalType":"int128","name":"strike64x64","type":"int128"},{"indexed":false,"internalType":"int128","name":"offsetStrike64x64","type":"int128"},{"indexed":false,"internalType":"int128","name":"spot64x64","type":"int128"},{"indexed":false,"internalType":"int128","name":"maxPrice64x64","type":"int128"},{"indexed":false,"internalType":"int128","name":"minPrice64x64","type":"int128"}],"name":"AuctionPricesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"epoch","type":"uint64"},{"indexed":false,"internalType":"enum AuctionStorage.Status","name":"status","type":"uint8"}],"name":"AuctionStatusSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"int128","name":"oldDeltaOffset","type":"int128"},{"indexed":false,"internalType":"int128","name":"newDeltaOffset","type":"int128"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"DeltaOffsetSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldExchangeHelper","type":"address"},{"indexed":false,"internalType":"address","name":"newExchangeHelper","type":"address"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"ExchangeHelperSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"message","type":"string"}],"name":"Log","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldMinSize","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newMinSize","type":"uint256"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"MinSizeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"epoch","type":"uint64"},{"indexed":false,"internalType":"uint128","name":"orderId","type":"uint128"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"int128","name":"price64x64","type":"int128"},{"indexed":false,"internalType":"uint256","name":"size","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isLimitOrder","type":"bool"}],"name":"OrderAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"epoch","type":"uint64"},{"indexed":false,"internalType":"uint128","name":"orderId","type":"uint128"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"}],"name":"OrderCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"epoch","type":"uint64"},{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"refund","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fill","type":"uint256"}],"name":"OrderWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPricer","type":"address"},{"indexed":false,"internalType":"address","name":"newPricer","type":"address"},{"indexed":false,"internalType":"address","name":"caller","type":"address"}],"name":"PricerSet","type":"event"},{"inputs":[],"name":"ERC20","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Pool","outputs":[{"internalType":"contract IPremiaPool","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Vault","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WETH","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"},{"internalType":"int128","name":"price64x64","type":"int128"},{"internalType":"uint256","name":"size","type":"uint256"}],"name":"addLimitOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"},{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"uint256","name":"maxCost","type":"uint256"}],"name":"addMarketOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"},{"internalType":"uint128","name":"orderId","type":"uint128"}],"name":"cancelLimitOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"clearingPrice64x64","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"finalizeAuction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"getAuction","outputs":[{"components":[{"internalType":"enum AuctionStorage.Status","name":"status","type":"uint8"},{"internalType":"uint64","name":"expiry","type":"uint64"},{"internalType":"int128","name":"strike64x64","type":"int128"},{"internalType":"int128","name":"maxPrice64x64","type":"int128"},{"internalType":"int128","name":"minPrice64x64","type":"int128"},{"internalType":"int128","name":"lastPrice64x64","type":"int128"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"uint256","name":"processedTime","type":"uint256"},{"internalType":"uint256","name":"totalContracts","type":"uint256"},{"internalType":"uint256","name":"totalContractsSold","type":"uint256"},{"internalType":"uint256","name":"totalUnclaimedContracts","type":"uint256"},{"internalType":"uint256","name":"totalPremiums","type":"uint256"},{"internalType":"uint256","name":"longTokenId","type":"uint256"}],"internalType":"struct AuctionStorage.Auction","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getDeltaOffset64x64","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"},{"internalType":"uint128","name":"orderId","type":"uint128"}],"name":"getOrderById","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"int128","name":"price64x64","type":"int128"},{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"address","name":"buyer","type":"address"}],"internalType":"struct OrderBook.Data","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"getStatus","outputs":[{"internalType":"enum AuctionStorage.Status","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"getTotalContracts","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"getTotalContractsSold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"buyer","type":"address"}],"name":"getUniqueOrderIds","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"epoch","type":"uint64"},{"internalType":"uint64","name":"expiry","type":"uint64"},{"internalType":"int128","name":"strike64x64","type":"int128"},{"internalType":"uint256","name":"longTokenId","type":"uint256"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"internalType":"struct AuctionStorage.InitAuction","name":"initAuction","type":"tuple"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"lastPrice64x64","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"},{"internalType":"address","name":"buyer","type":"address"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"priceCurve64x64","outputs":[{"internalType":"int128","name":"","type":"int128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"processAuction","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"setAuctionPrices","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"int128","name":"newDeltaOffset64x64","type":"int128"}],"name":"setDeltaOffset64x64","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newExchangeHelper","type":"address"}],"name":"setExchangeHelper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMinSize","type":"uint256"}],"name":"setMinSize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newPricer","type":"address"}],"name":"setPricer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address","name":"callee","type":"address"},{"internalType":"address","name":"allowanceTarget","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"address","name":"refundAddress","type":"address"}],"internalType":"struct IExchangeHelper.SwapArgs","name":"s","type":"tuple"},{"internalType":"uint64","name":"epoch","type":"uint64"},{"internalType":"int128","name":"price64x64","type":"int128"},{"internalType":"uint256","name":"size","type":"uint256"}],"name":"swapAndAddLimitOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address","name":"callee","type":"address"},{"internalType":"address","name":"allowanceTarget","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"address","name":"refundAddress","type":"address"}],"internalType":"struct IExchangeHelper.SwapArgs","name":"s","type":"tuple"},{"internalType":"uint64","name":"epoch","type":"uint64"},{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"uint256","name":"maxCost","type":"uint256"}],"name":"swapAndAddMarketOrder","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"epoch","type":"uint64"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101606040523480156200001257600080fd5b5060405162005ff438038062005ff48339810160408190526200003591620001fb565b83151560809081526001600160a01b0384166101008190526040805163e4a0ce2f60e01b81529051879387938793879360009363e4a0ce2f92600480820193918290030181865afa1580156200008f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000b591906200025e565b90506000608051620000cc578160200151620000cf565b81515b905081602001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000114573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200013a9190620002f2565b60ff1660a08160ff168152505081600001516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200018a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001b09190620002f2565b60ff1660c0526001600160a01b0390811660e05292831661012052501661014052506200031e945050505050565b80516001600160a01b0381168114620001f657600080fd5b919050565b600080600080608085870312156200021257600080fd5b845180151581146200022357600080fd5b93506200023360208601620001de565b92506200024360408601620001de565b91506200025360608601620001de565b905092959194509250565b6000608082840312156200027157600080fd5b604051608081016001600160401b0381118282101715620002a257634e487b7160e01b600052604160045260246000fd5b604052620002b083620001de565b8152620002c060208401620001de565b6020820152620002d360408401620001de565b6040820152620002e660608401620001de565b60608201529392505050565b6000602082840312156200030557600080fd5b815160ff811681146200031757600080fd5b9392505050565b60805160a05160c05160e051610100516101205161014051615bbe620004366000396000818161052201528181611fc901528181612102015281816127bb0152818161283201526128b001526000818161037901528181611271015281816115b8015281816116e8015281816147c0015261484601526000818161025001528181612b3d0152613c240152600081816106550152818161086201528181610f5c015281816111b0015281816116c501528181611be101528181611ff301528181612a520152612bb501526000613d4b015260008181613d6c01526149000152600081816122f20152818161236401528181612431015281816124ce01528181613c9d01528181613cfa01526148de0152615bbe6000f3fe6080604052600436106102045760003560e01c8063a16594b911610118578063cc4aa204116100a0578063d3f44d841161006f578063d3f44d84146106bf578063d999ec8f146106df578063da60d637146106ff578063df4c96701461071f578063f23a6e611461074c57600080fd5b8063cc4aa20414610643578063d07041e014610677578063d2639b621461068c578063d26fef61146106ac57600080fd5b8063b670b058116100e7578063b670b05814610564578063ba728b5f14610584578063ba98d741146105a4578063bc12e3d7146105d1578063bc197c81146105fe57600080fd5b8063a16594b9146104c3578063ac9650d8146104e3578063ad5c464814610510578063b044ab751461054457600080fd5b80632d2c44f21161019b57806379e1aa381161016a57806379e1aa38146103e35780637a4f8d3a146103f65780637e28e8bf146104245780637f32cf41146104445780638df5db82146104a357600080fd5b80632d2c44f21461036757806357530e871461039b578063579e792f146103b0578063750f0acc146103c357600080fd5b806321651f8e116101d757806321651f8e146102bf57806327f39951146102f257806329390370146103275780632a0d3a291461034757600080fd5b806301ffc9a71461020957806307f3b8bb1461023e5780630cfd168f1461028a57806318f4a50a1461029f575b600080fd5b34801561021557600080fd5b50610229610224366004614ef2565b610778565b60405190151581526020015b60405180910390f35b34801561024a57600080fd5b506102727f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610235565b61029d610298366004614f38565b6107bb565b005b3480156102ab57600080fd5b5061029d6102ba366004614f6b565b6108a8565b3480156102cb57600080fd5b506102df6102da366004614f6b565b610be6565b604051600f9190910b8152602001610235565b3480156102fe57600080fd5b5061031261030d366004614f6b565b610c1f565b60408051928352602083019190915201610235565b34801561033357600080fd5b5061029d610342366004614f9d565b610c35565b34801561035357600080fd5b5061029d610362366004614fc7565b610d8f565b34801561037357600080fd5b506102727f000000000000000000000000000000000000000000000000000000000000000081565b3480156103a757600080fd5b506102df610ec0565b61029d6103be366004614ff6565b610ecf565b3480156103cf57600080fd5b5061029d6103de366004614f6b565b610fab565b61029d6103f136600461505d565b61111f565b34801561040257600080fd5b50610416610411366004614f6b565b611200565b604051908152602001610235565b34801561043057600080fd5b506102df61043f366004614f6b565b61120b565b34801561045057600080fd5b5061046461045f3660046150b9565b611241565b604051610235919081518152602080830151600f0b90820152604080830151908201526060918201516001600160a01b03169181019190915260800190565b3480156104af57600080fd5b5061029d6104be36600461513e565b61125a565b3480156104cf57600080fd5b506102df6104de366004614f6b565b611462565b3480156104ef57600080fd5b506105036104fe3660046151ce565b611493565b604051610235919061529a565b34801561051c57600080fd5b506102727f000000000000000000000000000000000000000000000000000000000000000081565b34801561055057600080fd5b5061031261055f366004614f6b565b61159e565b34801561057057600080fd5b5061029d61057f3660046152fc565b611735565b34801561059057600080fd5b5061029d61059f366004614f6b565b611809565b3480156105b057600080fd5b506105c46105bf366004614f6b565b6118cd565b604051610235919061534d565b3480156105dd57600080fd5b506105f16105ec366004614f6b565b6118d8565b604051610235919061535b565b34801561060a57600080fd5b5061062a61061936600461552e565b63bc197c8160e01b95945050505050565b6040516001600160e01b03199091168152602001610235565b34801561064f57600080fd5b506102727f000000000000000000000000000000000000000000000000000000000000000081565b34801561068357600080fd5b506104166118e9565b34801561069857600080fd5b506104166106a7366004614f6b565b6118f3565b61029d6106ba3660046155d7565b61194b565b3480156106cb57600080fd5b5061029d6106da3660046150b9565b6119f8565b3480156106eb57600080fd5b5061029d6106fa366004614f9d565b611c62565b34801561070b57600080fd5b5061031261071a366004615616565b611dbc565b34801561072b57600080fd5b5061073f61073a366004614f9d565b611dd5565b6040516102359190615649565b34801561075857600080fd5b5061062a61076736600461568d565b63f23a6e6160e01b95945050505050565b6001600160e01b0319811660009081527f326d0c59a7612f6a9919e2a8ee333c80ba689d8ba2634de89c85cbb04832e705602052604081205460ff165b92915050565b600080516020615b698339815191528054600214156107f55760405162461bcd60e51b81526004016107ec906156f1565b60405180910390fd5b600281556000610803611e9b565b6001600160401b0386166000908152600282016020526040902090915061082981611ebf565b60008061083884848989611f09565b91509150600061084782611fbe565b905061088a3330610858848661573e565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001692919061217a565b61089985858b868c60006121e5565b50506001909355505050505050565b60006108b2611e9b565b6001600160401b0383166000908152600282016020526040902080549192509060ff1660048111156108e6576108e6615315565b6001146109055760405162461bcd60e51b81526004016107ec90615755565b6107088160030154610917919061573e565b421161095b5760405162461bcd60e51b815260206004820152601360248201527270726963652073657420746f6f206561726c7960681b60448201526064016107ec565b60018101546000600160801b909104600f0b131580610985575060018101546000600f9190910b13155b6109ca5760405162461bcd60e51b81526020600482015260166024820152751c1c9a58d95cc8185c9948185b1c9958591e481cd95d60521b60448201526064016107ec565b4281600301541115610bd7576000808360060160009054906101000a90046001600160a01b03166001600160a01b031663d33b48b56040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610a4a575060408051601f3d908101601f19168201909252610a4791810190615784565b60015b610ac357610a566157a1565b806308c379a01415610ab75750610a6b6157bd565b80610a765750610ab9565b7fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab81604051610aa59190615846565b60405180910390a16000925050610ac6565b505b3d6000803e3d6000fd5b91505b60068401548354604051631d94c9b360e01b81526101009091046001600160401b031660048201526001600160a01b0390911690631d94c9b390602401602060405180830381865afa925050508015610b3c575060408051601f3d908101601f19168201909252610b3991810190615784565b60015b610ba957610b486157a1565b806308c379a01415610ab75750610b5d6157bd565b80610b685750610ab9565b7fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab81604051610b979190615846565b60405180910390a16000915050610bac565b90505b600082600f0b138015610bc25750600081600f0b135b15610bd457610bd484848785856122cb565b50505b610be181846125ca565b505050565b600080610bf1611e9b565b6001600160401b03841660009081526002820160205260409020909150610c1781612624565b949350505050565b600080610c2c833361269a565b91509150915091565b600080516020615b49833981519152546001600160a01b03163314610c6c5760405162461bcd60e51b81526004016107ec90615859565b6000610c76611e9b565b90506001600160a01b038216610cc55760405162461bcd60e51b81526020600482015260146024820152731859191c995cdcc81b9bdd081c1c9bdd9a59195960621b60448201526064016107ec565b60068101546001600160a01b0383811691161415610d1e5760405162461bcd60e51b81526020600482015260166024820152751b995dc81859191c995cdcc8195c5d585b1cc81bdb1960521b60448201526064016107ec565b6006810154604080516001600160a01b03928316815291841660208301523382820152517faa40df73b7e66d2e4e3a90deb47486303ca82739a96c5595ba8c68d00482fed29181900360600190a160060180546001600160a01b0319166001600160a01b0392909216919091179055565b600080516020615b49833981519152546001600160a01b03163314610dc65760405162461bcd60e51b81526004016107ec90615859565b6000610dd0611e9b565b9050600082600f0b13610e125760405162461bcd60e51b815260206004820152600a602482015269064656c7461203c3d20360b41b60448201526064016107ec565b68010000000000000000600f83900b12610e5a5760405162461bcd60e51b815260206004820152600960248201526864656c7461203e203160b81b60448201526064016107ec565b805460408051600f92830b81529184900b60208301523382820152517f8ade3304a9dbce06100c268f7f1f6e66c1627bf10e8a495977290d0625148eb99181900360600190a180546001600160801b0319166001600160801b0392909216919091179055565b6000610eca6126c2565b905090565b600080516020615b69833981519152805460021415610f005760405162461bcd60e51b81526004016107ec906156f1565b600281556000610f0e611e9b565b6001600160401b03861660009081526002820160205260409020909150610f34816126d5565b6000610f4183878761270a565b6005840154909150600090610f80906001600160a01b03168a7f00000000000000000000000000000000000000000000000000000000000000006127a9565b9050610f8d818333612a32565b610f9c84848a8a8a60016121e5565b50506001909255505050505050565b600080516020615b69833981519152805460021415610fdc5760405162461bcd60e51b81526004016107ec906156f1565b600281556000610fea611e9b565b6001600160401b0384166000908152600282016020526040902080549192509060ff16600481111561101e5761101e615315565b600314806110415750805460ff16600481111561103d5761103d615315565b6004145b61108d5760405162461bcd60e51b815260206004820181905260248201527f73746174757320213d2070726f636573736564207c7c2063616e63656c6c656460448201526064016107ec565b805460ff1660048111156110a3576110a3615315565b6003141561110c5760058101546110bd9062015180615890565b42101561110c5760405162461bcd60e51b815260206004820152601960248201527f686f6c6420706572696f6420686173206e6f7420656e6465640000000000000060448201526064016107ec565b6111168285612a90565b50506001905550565b600080516020615b698339815191528054600214156111505760405162461bcd60e51b81526004016107ec906156f1565b60028155600061115e611e9b565b6001600160401b0386166000908152600282016020526040902090915061118481611ebf565b60008061119384848989611f09565b600586015491935091506000906111d4906001600160a01b03168b7f00000000000000000000000000000000000000000000000000000000000000006127a9565b90506111e1818333612a32565b6111f085858b868c60006121e5565b5050600190935550505050505050565b60006107b582612c30565b600080611216611e9b565b6001600160401b03841660009081526002820160205260409020909150610c178160020154600f0b90565b611249614e04565b6112538383612c5f565b9392505050565b6000611264611e9b565b9050336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146112c75760405162461bcd60e51b8152602060048201526006602482015265085d985d5b1d60d21b60448201526064016107ec565b60006112d1611e9b565b83516001600160401b031660009081526002820160205260408120919250815460ff16600481111561130557611305615315565b146113525760405162461bcd60e51b815260206004820152601760248201527f73746174757320213d20756e696e697469616c697a656400000000000000000060448201526064016107ec565b8360a00151846080015110158061136c5750836080015142115b80611383575083602001516001600160401b031642115b80611396575060008460400151600f0b13155b806113a357506060840151155b156113d45783516001600160401b03166000908152600283016020526040902084516113cf9190612ca2565b61145c565b6020840151815460408601516001600160801b0316600160481b0278ffffffffffffffffffffffffffffffff000000000000000000196001600160401b039093166101000292909216610100600160c81b0319909116171781556080840151600382015560a084015160048201556060840151600a820155835161145c908290600190612cb1565b50505050565b60008061146d611e9b565b6001600160401b03841660009081526002820160205260409020909150610c1781612d20565b6060816001600160401b038111156114ad576114ad6150fc565b6040519080825280602002602001820160405280156114e057816020015b60608152602001906001900390816114cb5790505b50905060005b828110156115975760008030868685818110611504576115046158a8565b905060200281019061151691906158be565b604051611524929190615904565b600060405180830381855af49150503d806000811461155f576040519150601f19603f3d011682016040523d82523d6000602084013e611564565b606091505b50915091508115610ab95780848481518110611582576115826158a8565b602002602001018190525050506001016114e6565b5092915050565b60008060006115ab611e9b565b9050336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461160e5760405162461bcd60e51b8152602060048201526006602482015265085d985d5b1d60d21b60448201526064016107ec565b6000611618611e9b565b6001600160401b0386166000908152600282016020526040902080549192509060ff16600481111561164c5761164c615315565b6002146116915760405162461bcd60e51b81526020600482015260136024820152721cdd185d1d5cc8084f48199a5b985b1a5e9959606a1b60448201526064016107ec565b6116b081600701546116a78360020154600f0b90565b600f0b90612dd2565b6009820181905561170d906001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016907f000000000000000000000000000000000000000000000000000000000000000090612e3a565b42600582015561171f81600388612cb1565b8060090154816007015494509450505050915091565b600080516020615b49833981519152546001600160a01b0316331461176c5760405162461bcd60e51b81526004016107ec90615859565b6000611776611e9b565b9050600082116117c05760405162461bcd60e51b815260206004820152601560248201527476616c75652065786365656473206d696e696d756d60581b60448201526064016107ec565b600181015460408051918252602082018490523382820152517f1f1913f02d98f08a2ed8c776d0559838fe3804f17663b57486c274065646ceb99181900360600190a160010155565b6000611813611e9b565b6001600160401b038316600090815260028201602052604090206004810154919250906118439062015180615890565b4211801561188557506001815460ff16600481111561186457611864615315565b148061188557506002815460ff16600481111561188357611883615315565b145b1561189457610be18184612ca2565b806003015442101580156118bd57506001815460ff1660048111156118bb576118bb615315565b145b15610be157610be1828285612e6a565b60006107b582612edc565b6118e0614e38565b6107b582612f0b565b6000610eca613019565b6000806118fe611e9b565b6001600160401b0384166000908152600282016020526040902060038101549192509015801590611933575080600301544210155b1561194157610c178461302c565b5060009392505050565b600080516020615b6983398151915280546002141561197c5760405162461bcd60e51b81526004016107ec906156f1565b60028155600061198a611e9b565b6001600160401b038616600090815260028201602052604090209091506119b0816126d5565b60006119bd83878761270a565b905060006119ca82611fbe565b90506119db3330610858848661573e565b6119ea84848a8a8a60016121e5565b505060019092555050505050565b600080516020615b69833981519152805460021415611a295760405162461bcd60e51b81526004016107ec906156f1565b600281556000611a37611e9b565b6001600160401b03851660009081526002820160205260409020909150611a5d816126d5565b6000846001600160801b031611611aa95760405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a59081bdc99195c881a5960821b60448201526064016107ec565b6001600160401b0385166000908152600383016020526040812090611ad7826001600160801b03881661305b565b60608101519091506001600160a01b0316611b2b5760405162461bcd60e51b81526020600482015260146024820152731bdc99195c88191bd95cc81b9bdd08195e1a5cdd60621b60448201526064016107ec565b60608101516001600160a01b03163314611b7d5760405162461bcd60e51b8152602060048201526013602482015272313abcb2b910109e9036b9b39739b2b73232b960691b60448201526064016107ec565b611b90826001600160801b0388166130b4565b50611b9c848888613391565b82600301544210611bb257611bb2848489612e6a565b6000611bd282604001518360200151600f0b612dd290919063ffffffff16565b9050611c086001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163383612e3a565b604080516001600160801b03891681523360208201526001600160401b038a16917fb7a419a9cad0cf4a1610023a7ee67f873ba51a63189b14b543ee6f31db8b7f3c910160405180910390a2505060019093555050505050565b600080516020615b49833981519152546001600160a01b03163314611c995760405162461bcd60e51b81526004016107ec90615859565b6000611ca3611e9b565b90506001600160a01b038216611cf25760405162461bcd60e51b81526020600482015260146024820152731859191c995cdcc81b9bdd081c1c9bdd9a59195960621b60448201526064016107ec565b60058101546001600160a01b0383811691161415611d4b5760405162461bcd60e51b81526020600482015260166024820152751b995dc81859191c995cdcc8195c5d585b1cc81bdb1960521b60448201526064016107ec565b6005810154604080516001600160a01b03928316815291841660208301523382820152517f045d485de10addb86db6ce795700266572ef7d9132df09a384062b5e82a093739181900360600190a160050180546001600160a01b0319166001600160a01b0392909216919091179055565b600080611dc9848461269a565b915091505b9250929050565b60606000611de1611e9b565b6001600160a01b03841660009081526004820160205260408120919250611e078261344e565b6001600160401b03811115611e1e57611e1e6150fc565b604051908082528060200260200182016040528015611e47578160200160208202803683370190505b50905060005b611e568361344e565b811015611e92576000611e698483613458565b905080838381518110611e7e57611e7e6158a8565b602090810291909101015250600101611e4d565b50949350505050565b7f7f75137652cf01fd4e0a016c479a4a2bdc1018772b7fc0eab68410c366c40cbb90565b805460ff166004811115611ed557611ed5615315565b600114611ef45760405162461bcd60e51b81526004016107ec90615755565b611efd81613464565b611f06816134fa565b50565b6000808560010154841015611f515760405162461bcd60e51b815260206004820152600e60248201526d73697a65203c206d696e696d756d60901b60448201526064016107ec565b6000611f5c86612d20565b90506000611f6e600f83900b87612dd2565b905080851015611fb15760405162461bcd60e51b815260206004820152600e60248201526d18dbdcdd080f881b585e10dbdcdd60921b60448201526064016107ec565b9097909650945050505050565b60008034156107b5577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03167f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161461205d5760405162461bcd60e51b81526020600482015260126024820152710c6ded8d8c2e8cae4c2d840427a40ee8aa8960731b60448201526064016107ec565b823411156120fd57604051600090339034869003908381818185875af1925050503d80600081146120aa576040519150601f19603f3d011682016040523d82523d6000602084013e6120af565b606091505b50509050806120f45760405162461bcd60e51b8152602060048201526011602482015270115512081c99599d5b990819985a5b1959607a1b60448201526064016107ec565b83915050612100565b50345b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561215b57600080fd5b505af115801561216f573d6000803e3d6000fd5b505050505092915050565b6040516001600160a01b038085166024830152831660448201526064810182905261145c9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261358c565b6001600160401b038416600090815260038701602052604081206122149061220f9086863361365e565b613808565b905060006122228683613865565b33600090815260048a016020526040902090915061224090826138a4565b508660030154421061225757612257888888612e6a565b604080516001600160801b0384168152336020820152600f87900b918101919091526060810185905283151560808201526001600160401b038716907f02270113c1297ab39d725cfb6962831ea118df963a68a6ce2fe974bef26954659060a0015b60405180910390a25050505050505050565b83548554600160481b909104600f90810b916000916122ec9184910b6138b0565b905060007f000000000000000000000000000000000000000000000000000000000000000061232857612323600f84900b836138e7565b612336565b612336600f84900b8361391a565b6006890154604051631b1aac9960e31b8152600f88810b600483015286810b602483015287900b60448201527f0000000000000000000000000000000000000000000000000000000000000000151560648201529192506001600160a01b03169063d8d564c890608401602060405180830381865afa1580156123bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e19190615784565b6001880180546001600160801b0319166001600160801b03929092169190911790556006880154604051631b1aac9960e31b8152600f87810b600483015283810b602483015286900b60448201527f0000000000000000000000000000000000000000000000000000000000000000151560648201526001600160a01b039091169063d8d564c890608401602060405180830381865afa158015612489573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ad9190615784565b6001880180546001600160801b03928316600160801b0292169190911790557f00000000000000000000000000000000000000000000000000000000000000001561255c57600187015461250490600f0b8661394d565b6001880180546001600160801b0319166001600160801b0392909216919091179081905561253c90600160801b9004600f0b8661394d565b6001880180546001600160801b03928316600160801b0292169190911790555b600187015460408051600f86810b825284810b602083015288810b9282019290925282820b6060820152600160801b909204900b60808201526001600160401b038716907f447e2e3d9b721c94b61250f439e96e626afd0552cb425d4c46da503a58096a779060a0016122b9565b60018201546000600f9190910b1315806125f4575060018201546000600160801b909104600f0b13155b8061261157506001820154600160801b8104600f90810b91900b13155b15612620576126208282612ca2565b5050565b60006002825460ff16600481111561263e5761263e615315565b148061265f57506003825460ff16600481111561265d5761265d615315565b145b8061267f57506004825460ff16600481111561267d5761267d615315565b145b15612691576002820154600f0b6107b5565b6107b582612d20565b60008060006126a7611e9b565b90506126b681600187876139a5565b92509250509250929050565b60006126cc611e9b565b54600f0b919050565b805460ff1660048111156126eb576126eb615315565b600114611efd5760405162461bcd60e51b81526004016107ec90615755565b60008083600f0b1361274b5760405162461bcd60e51b815260206004820152600a60248201526907072696365203c3d20360b41b60448201526064016107ec565b83600101548210156127905760405162461bcd60e51b815260206004820152600e60248201526d73697a65203c206d696e696d756d60901b60448201526064016107ec565b60006127a0600f85900b84612dd2565b95945050505050565b600034156128db576001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166127e86020850185614f9d565b6001600160a01b0316146128305760405162461bcd60e51b815260206004820152600f60248201526e0e8ded6cadc92dc40427a40ee8aa89608b1b60448201526064016107ec565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561288b57600080fd5b505af115801561289f573d6000803e3d6000fd5b506128db9350506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016915086905034612e3a565b60208301351561290c5761290c3385602086018035906128fb9088614f9d565b6001600160a01b031692919061217a565b60006001600160a01b038516632e25a7ab61292a6020870187614f9d565b856129393460208a0135615890565b61294960808a0160608b01614f9d565b61295960a08b0160808c01614f9d565b61296660a08c018c6158be565b61297660e08e0160c08f01614f9d565b6040518963ffffffff1660e01b8152600401612999989796959493929190615914565b6020604051808303816000875af11580156129b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129dc919061597d565b90508360400135811015610c175760405162461bcd60e51b815260206004820152601c60248201527f6e6f7420656e6f756768206f75747075742066726f6d2074726164650000000060448201526064016107ec565b81831115612a7957610be181612a48848661573e565b6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169190612e3a565b82821115610be157610be18130610858868661573e565b600080612aa084600085336139a5565b91509150612ab084846000613391565b600080612abe868685613bb8565b915091508115612ae0578015612adb57612ad88185615890565b93505b600092505b8215612ba2576001600160401b0385166000908152600287016020526040808220600a01549051637921219560e11b815230600482015233602482015260448101919091526064810185905260a0608482015260a48101919091527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063f242432a9060c401600060405180830381600087803b158015612b8957600080fd5b505af1158015612b9d573d6000803e3d6000fd5b505050505b8315612bdc57612bdc6001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000163386612e3a565b60408051338152602081018690529081018490526001600160401b038616907f6c2dbbc7b415aab71b377f227d7a334f34899818306efbc6262b9ce85c4306be9060600160405180910390a2505050505050565b6000612c3a611e9b565b6001600160401b03909216600090815260029290920160205250604090206007015490565b612c67614e04565b6000612c71611e9b565b6001600160401b0385166000908152600391909101602052604090209050610c17816001600160801b03851661305b565b60006009830155612620826004835b82548290849060ff19166001836004811115612ccf57612ccf615315565b021790555082546040516001600160401b038316917f72d4affeac2e73f129f6fe359896ed8802d8bc11b826f9ac67cf50fcc7d3cc4d91612d139160ff169061534d565b60405180910390a2505050565b60038101546004820154600091908290612d3b90839061573e565b6001850154909150600f81810b91600160801b9004900b428410612d625750949350505050565b85600401544210612d765795945050505050565b6000612d82854261573e565b90506000612d908286613da8565b90506000612da2600f86900b856138e7565b90506000612db4600f84900b836138b0565b9050612dc4600f87900b826138e7565b9a9950505050505050505050565b600081612de1575060006107b5565b600083600f0b1215612df257600080fd5b600f83900b6001600160801b038316810260401c90608084901c026001600160c01b03811115612e2157600080fd5b60401b8119811115612e3257600080fd5b019392505050565b6040516001600160a01b038316602482015260448101829052610be190849063a9059cbb60e01b906064016121ae565b612e7482826125ca565b6004825460ff166004811115612e8c57612e8c615315565b14158015612ead5750612e9f8382613ddf565b80612ead5750816004015442115b15610be157600782015415612ed25760078201546008830155610be182600283612cb1565b610be18282612ca2565b6000612ee6611e9b565b6001600160401b03909216600090815260029290920160205250604090205460ff1690565b612f13614e38565b612f1b611e9b565b6001600160401b038316600090815260029190910160205260409081902081516101c081019092528054829060ff166004811115612f5b57612f5b615315565b6004811115612f6c57612f6c615315565b815281546101008082046001600160401b03166020840152600160481b909104600f90810b6040840152600184015480820b6060850152600160801b9004810b60808401526002840154900b60a0830152600383015460c0830152600483015460e08301526005830154908201526006820154610120820152600782015461014082015260088201546101608201526009820154610180820152600a909101546101a09091015292915050565b6000613023611e9b565b60010154905090565b6000613036611e9b565b6001600160401b03909216600090815260029290920160205250604090206006015490565b613063614e04565b506000908152600391820160209081526040918290208251608081018452815481526001820154600f0b928101929092526002810154928201929092529101546001600160a01b0316606082015290565b81546000908214156130cd576130ca8383613f45565b83555b6000828152600384016020526040812080548291829182919087146130fa576000955050505050506107b5565b600581015415158061310f5750600681015415155b156132cc5760058101541561314a578760030160006131358a84600001600001546141de565b81526020019081526020016000209450613172565b8760030160006131618a8460000160000154613f45565b815260200190815260200160002094505b6004850154600090815260038901602052604090208554600582015491955092508214156131ca57600685015460058501819055156131ca576006850154600090815260038901602052604090208454600482015592505b8454600685015414156132075760058501546006850181905515613207576005850154600090815260038901602052604090208454600482015592505b6004808201549086018190551561325f5760048101546000908152600389016020526040902081546005820154919550141561324557845460058501555b80546006850154141561325a57845460068501555b613267565b845460028901555b60058082015490860181905515613297576005810154600090815260038901602052604090208554600482015592505b600680820154908601819055156132c7576006810154600090815260038901602052604090208554600482015592505b613329565b6004810154156133215760048101546000908152600389016020526040902081546005820154919550141561330357600060058501555b80546006850154141561331857600060068501555b83549150613329565b600060028901555b60008082556001820180546001600160801b0319169055600282018190556003820180546001600160a01b031916905560048201819055600582018190556006820181905560078201558115613383576133838883614465565b506001979650505050505050565b3360009081526004840160205260408120905b6133ad8261344e565b8110156134475760006133c08383613458565b9050608081901c816001600160801b0386161580156133f05750866001600160401b0316826001600160401b0316145b806134285750856001600160801b0316816001600160801b03161480156134285750866001600160401b0316826001600160401b0316145b1561343957613437858461454c565b505b5050508060010190506133a4565b5050505050565b60006107b5825490565b60006112538383614558565b60008160030154116134b05760405162461bcd60e51b81526020600482015260156024820152741cdd185c9d081d1a5b59481a5cc81b9bdd081cd95d605a1b60448201526064016107ec565b8060030154421015611f065760405162461bcd60e51b8152602060048201526013602482015272185d58dd1a5bdb881b9bdd081cdd185c9d1959606a1b60448201526064016107ec565b60008160040154116135445760405162461bcd60e51b8152602060048201526013602482015272195b99081d1a5b59481a5cc81b9bdd081cd95d606a1b60448201526064016107ec565b8060040154421115611f065760405162461bcd60e51b8152602060048201526011602482015270185d58dd1a5bdb881a185cc8195b991959607a1b60448201526064016107ec565b60006135e1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166145de9092919063ffffffff16565b805190915015610be157808060200190518101906135ff9190615996565b610be15760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016107ec565b6000846001015460016136719190615890565b60018601819055855460009061368890889061305b565b602081015188549192509015806136a4575080600f0b87600f0b135b156136ad578288555b60008381526003890160205260409020548314156136fe576000838152600389016020526040902060010154600f88810b91900b14156136f257829350505050610c17565b6136fc88846130b4565b505b600088600201546000141561371557600289018490555b6002890154600090815260038a01602052604090205b805461378157848155600481018290556001810180546001600160801b0319166001600160801b038b16179055600281018890556003810180546001600160a01b0319166001600160a01b0389161790556137ed565b80546001820154909250600f90810b908a900b136137c35760068101546137aa57600681018590555b60060154600090815260038a016020526040902061372b565b60058101546137d457600581018590555b60050154600090815260038a016020526040902061372b565b80546137fa908b90614465565b509298975050505050505050565b60006001600160801b038211156138615760405162461bcd60e51b815260206004820152601c60248201527f53616665436173743a2076616c756520646f6573206e6f74206669740000000060448201526064016107ec565b5090565b60003060601b6001600160801b03831661389a67ffffffffffffffff60801b608087901b166001600160c01b03198416615890565b610c179190615890565b600061125383836145ed565b6000600f83810b9083900b0260401d60016001607f1b031981128015906138de575060016001607f1b038113155b61125357600080fd5b6000600f82810b9084900b0360016001607f1b031981128015906138de575060016001607f1b0381131561125357600080fd5b6000600f83810b9083900b0160016001607f1b031981128015906138de575060016001607f1b0381131561125357600080fd5b600081600f0b6000141561396057600080fd5b600082600f0b604085600f0b901b8161397b5761397b6159b8565b05905060016001607f1b031981128015906138de575060016001607f1b0381131561125357600080fd5b6001600160401b038216600090815260028501602090815260408083206003880190925282208291908280806139da85612624565b600886015490915060006139f66139ef875490565b879061305b565b90505b8051600090613a09908890613f45565b90508a6001600160a01b031682606001516001600160a01b03161415613b6157600080613a4a84604001518560200151600f0b612dd290919063ffffffff16565b905060048a5460ff166004811115613a6457613a64615315565b14158015613a725750600085115b8015613a88575085600f0b8460200151600f0b12155b15613b24576000613aa9856040015188600f0b612dd290919063ffffffff16565b90508585604001511115613ae457613ac5600f88900b87612dd2565b9050613ad18689615890565b9750613add8684615890565b9250613b08565b6040850151613af39089615890565b9750846040015183613b059190615890565b92505b613b12818361573e565b613b1c908a615890565b985050613b31565b613b2e8189615890565b97505b8e613b5e57818a6008016000828254613b4a919061573e565b90915550508351613b5c908a906130b4565b505b50505b8215613b8e578282604001511115613b7c5760009250613b8e565b6040820151613b8b908461573e565b92505b613b98878261305b565b8051909250151590506139f95750929b919a509098505050505050505050565b6001600160401b0380831660009081526002850160205260408120805491928392610100810490911690600160481b9004600f0b42821115613c035760008094509450505050613da0565b60405163098df99d60e11b81526001600160401b03831660048201526000907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063131bf33a90602401602060405180830381865afa158015613c73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c979190615784565b905060007f00000000000000000000000000000000000000000000000000000000000000008015613ccd575082600f0b82600f0b135b15613cf857613cf1886116a784613ce8600f82900b886138e7565b600f0b9061394d565b9050613d95565b7f0000000000000000000000000000000000000000000000000000000000000000158015613d2b575081600f0b83600f0b135b15613d95576000613d44896116a7600f87900b866138e7565b9050613d917f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000008361463c565b9150505b600196509450505050505b935093915050565b600081613db457600080fd5b6000613dc08484614659565b905060016001607f1b036001600160801b038216111561125357600080fd5b6001600160401b038116600090815260038301602090815260408083206002860190925282206006810154613e3f576000613e19826147bb565b905060008111613e3957613e2d8286612ca2565b600093505050506107b5565b60068201555b6000806000613e56613e4f865490565b869061305b565b90505b8051600090613e69908790613f45565b9050613e7485612624565b600f0b8260200151600f0b1215613e8b5750613f12565b60068501546040830151613e9f9086615890565b10613ee15750602001516002840180546001600160801b0319166001600160801b039092169190911790555050600681015460079091015550600190506107b5565b6040820151613ef09085615890565b60208301519094509250613f04868261305b565b805190925015159050613e59575b506002830180546001600160801b0319166001600160801b03929092169190911790556007909101555060009392505050565b600081815260038301602052604081208054613f655760009150506107b5565b613f6d614ebd565b60068201541561409a5750600680820154600090815260038087016020908152604092839020835161012081018552815460a082019081526001830154600f0b60c0830152600283015460e0830152938201546001600160a01b03166101008201529283526004810154918301919091526005810154928201929092529181015460608301526007015460808201525b60408101511561408f5760409081015160009081526003808701602090815291839020835161012081018552815460a082019081526001830154600f0b60c0830152600283015460e0830152928201546001600160a01b031661010082015291825260048101549282019290925260058201549281019290925260068101546060830152600701546080820152613ffd565b515191506107b59050565b6004820154156141d357506004810154600081815260038087016020908152604092839020835161012081018552865460a082019081526001880154600f0b60c0830152600288015460e0830152938701546001600160a01b0316610100820152928352908201939093526005840154918101919091526006830154606082015260078301546080820152905b81515160058201541415614140575492506107b5915050565b600481015461414e576141d1565b6040805161012081018252825460a082019081526001840154600f0b60c0830152600284015460e08301526003808501546001600160a01b03166101008401529082526004840154602080840182905260058601548486015260068601546060850152600790950154608084015260009081529089019093529120909150614127565b505b506000949350505050565b6000818152600383016020526040812080546141fe5760009150506107b5565b614206614ebd565b60058201541561432e5750600580820154600090815260038087016020908152604092839020835161012081018552815460a082019081526001830154600f0b60c0830152600283015460e0830152938201546001600160a01b031661010082015292835260048101549183019190915292830154918101919091526006820154606082015260079091015460808201525b60608101511561408f57606090810151600090815260038087016020908152604092839020835161012081018552815460a082019081526001830154600f0b60c0830152600283015460e0830152938201546001600160a01b0316610100820152928352600481015491830191909152600581015492820192909252600682015492810192909252600701546080820152614298565b6004820154156141d357506004810154600081815260038087016020908152604092839020835161012081018552865460a082019081526001880154600f0b60c0830152600288015460e0830152938701546001600160a01b0316610100820152928352908201939093526005840154918101919091526006830154606082015260078301546080820152905b815151600682015414156143d4575492506107b5915050565b60048101546143e2576141d1565b6040805161012081018252825460a082019081526001840154600f0b60c0830152600284015460e08301526003808501546001600160a01b031661010084015290825260048401546020808401829052600586015484860152600686015460608501526007909501546080840152600090815290890190935291209091506143bb565b600081815260038301602052604090205b805460009061448690859061493c565b905080600214156144c35761449f84836005015461493c565b60001914156144b6576144b6848360050154614974565b81546144c3908590614a68565b8060011914156144fe576144db84836006015461493c565b600114156144f1576144f1848360060154614a68565b81546144fe908590614974565b8060001913158015614511575060018113155b15614523578154614523908590614b4b565b60048201546145325750505050565b506004015460009081526003830160205260409020614476565b60006112538383614b9a565b815460009082106145b65760405162461bcd60e51b815260206004820152602260248201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604482015261647360f01b60648201526084016107ec565b8260000182815481106145cb576145cb6158a8565b9060005260206000200154905092915050565b6060610c178484600085614c67565b6000818152600183016020526040812054614634575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107b5565b5060006107b5565b6000806146498386614d67565b90506127a0600f82900b85614d7d565b60008161466557600080fd5b60006001600160c01b0384116146905782604085901b81614688576146886159b8565b0490506147a7565b60c084811c64010000000081106146a9576020918201911c5b6201000081106146bb576010918201911c5b61010081106146cc576008918201911c5b601081106146dc576004918201911c5b600481106146ec576002918201911c5b600281106146fb576001820191505b60bf820360018603901c6001018260ff0387901b8161471c5761471c6159b8565b0492506001600160801b0383111561473357600080fd5b608085901c83026001600160801b038616840260c088901c604089901b8281101561475f576001820391505b608084901b92900382811015614776576001820391505b829003608084901c821461478c5761478c6159ce565b88818161479b5761479b6159b8565b04870196505050505050505b6001600160801b0381111561125357600080fd5b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634ac8eb5f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561481c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614840919061597d565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a19471196040518163ffffffff1660e01b8152600401602060405180830381865afa1580156148a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148c6919061597d565b90508082116148d6576000610c17565b8354610c17907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000000090600160481b9004600f0b614934858761573e565b929190614d98565b6000818152600383016020526040808220600681015483528183206007908101546005830154855292842001549091610c17916159e4565b60008181526003830160205260409020600681015461499257600080fd5b6006810180546000908152600385016020526040812060048085015490820181905591909255156149fe576004820154600090815260038501602052604090208254600582015414156149e757815460058201555b8254600682015414156149fc57815460068201555b505b600581015415614a2d576005810154600090815260038501602052604090208054600684015582546004909101555b805460048084019190915582546005830155810154614a4e57805460028501555b8154614a5b908590614b4b565b805461145c908590614b4b565b600081815260038301602052604090206005810154614a8657600080fd5b600581018054600090815260038501602052604081206004808501549082018190559190925515614af257600482015460009081526003850160205260409020825460058201541415614adb57815460058201555b825460068201541415614af057815460068201555b505b600681015415614b2257600681015460008181526003860160205260409020600584019190915582546004909101555b805460048084019190915582546006830155810154614a4e57805460028501558154614a5b9085905b600081815260038301602052604080822060058101548352818320600790810154600683015485529290932090920154614b859190614dee565b614b90906001615890565b6007909101555050565b60008181526001830160205260408120548015614c5d57835460009085906000198101908110614bcc57614bcc6158a8565b9060005260206000200154905080856000016001840381548110614bf257614bf26158a8565b6000918252602080832090910192909255918252600186019052604090208190558354849080614c2457614c24615a23565b600190038181906000526020600020016000905590558360010160008481526020019081526020016000206000905560019150506107b5565b60009150506107b5565b6060843b614ccb5760405162461bcd60e51b815260206004820152602b60248201527f416464726573735574696c733a2066756e6374696f6e2063616c6c20746f206e60448201526a1bdb8b58dbdb9d1c9858dd60aa1b60648201526084016107ec565b600080866001600160a01b03168587604051614ce79190615a39565b60006040518083038185875af1925050503d8060008114614d24576040519150601f19603f3d011682016040523d82523d6000602084013e614d29565b606091505b50915091508115614d3d579150610c179050565b805115614d4d5780518082602001fd5b8360405162461bcd60e51b81526004016107ec9190615846565b600061125383614d7884600a615b39565b613da8565b6000611253614d8d83600a615b39565b600f85900b90612dd2565b600081600f0b60001415614dae57506000610c17565b8315614dbb575083610c17565b6000614dc78685614d67565b9050614de484614ddb600f84900b8661394d565b600f0b90614d7d565b9695505050505050565b6000818310614dfe5750816107b5565b50919050565b6040518060800160405280600081526020016000600f0b81526020016000815260200160006001600160a01b031681525090565b604080516101c08101909152806000815260200160006001600160401b031681526020016000600f0b81526020016000600f0b81526020016000600f0b81526020016000600f0b815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a00160405280614ed0614e04565b8152602001600081526020016000815260200160008152602001600081525090565b600060208284031215614f0457600080fd5b81356001600160e01b03198116811461125357600080fd5b80356001600160401b0381168114614f3357600080fd5b919050565b600080600060608486031215614f4d57600080fd5b614f5684614f1c565b95602085013595506040909401359392505050565b600060208284031215614f7d57600080fd5b61125382614f1c565b80356001600160a01b0381168114614f3357600080fd5b600060208284031215614faf57600080fd5b61125382614f86565b80600f0b8114611f0657600080fd5b600060208284031215614fd957600080fd5b813561125381614fb8565b600060e08284031215614dfe57600080fd5b6000806000806080858703121561500c57600080fd5b84356001600160401b0381111561502257600080fd5b61502e87828801614fe4565b94505061503d60208601614f1c565b9250604085013561504d81614fb8565b9396929550929360600135925050565b6000806000806080858703121561507357600080fd5b84356001600160401b0381111561508957600080fd5b61509587828801614fe4565b9450506150a460208601614f1c565b93969395505050506040820135916060013590565b600080604083850312156150cc57600080fd5b6150d583614f1c565b915060208301356001600160801b03811681146150f157600080fd5b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b0381118282101715615137576151376150fc565b6040525050565b600060c0828403121561515057600080fd5b60405160c081018181106001600160401b0382111715615172576151726150fc565b60405261517e83614f1c565b815261518c60208401614f1c565b6020820152604083013561519f81614fb8565b80604083015250606083013560608201526080830135608082015260a083013560a08201528091505092915050565b600080602083850312156151e157600080fd5b82356001600160401b03808211156151f857600080fd5b818501915085601f83011261520c57600080fd5b81358181111561521b57600080fd5b8660208260051b850101111561523057600080fd5b60209290920196919550909350505050565b60005b8381101561525d578181015183820152602001615245565b8381111561145c5750506000910152565b60008151808452615286816020860160208601615242565b601f01601f19169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156152ef57603f198886030184526152dd85835161526e565b945092850192908501906001016152c1565b5092979650505050505050565b60006020828403121561530e57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6005811061534957634e487b7160e01b600052602160045260246000fd5b9052565b602081016107b5828461532b565b60006101c08201905061536f82845161532b565b602083015161538960208401826001600160401b03169052565b50604083015161539e6040840182600f0b9052565b5060608301516153b36060840182600f0b9052565b5060808301516153c86080840182600f0b9052565b5060a08301516153dd60a0840182600f0b9052565b5060c0838101519083015260e08084015190830152610100808401519083015261012080840151908301526101408084015190830152610160808401519083015261018080840151908301526101a092830151929091019190915290565b600082601f83011261544c57600080fd5b813560206001600160401b03821115615467576154676150fc565b8160051b60405161547a83830182615112565b9283528481018201928281018785111561549357600080fd5b83870192505b848310156154b05782358152918301918301615499565b509695505050505050565b600082601f8301126154cc57600080fd5b81356001600160401b038111156154e5576154e56150fc565b6040516154fc601f8301601f191660200182615112565b81815284602083860101111561551157600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561554657600080fd5b61554f86614f86565b945061555d60208701614f86565b935060408601356001600160401b038082111561557957600080fd5b61558589838a0161543b565b9450606088013591508082111561559b57600080fd5b6155a789838a0161543b565b935060808801359150808211156155bd57600080fd5b506155ca888289016154bb565b9150509295509295909350565b6000806000606084860312156155ec57600080fd5b6155f584614f1c565b9250602084013561560581614fb8565b929592945050506040919091013590565b6000806040838503121561562957600080fd5b61563283614f1c565b915061564060208401614f86565b90509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561568157835183529284019291840191600101615665565b50909695505050505050565b600080600080600060a086880312156156a557600080fd5b6156ae86614f86565b94506156bc60208701614f86565b9350604086013592506060860135915060808601356001600160401b038111156156e557600080fd5b6155ca888289016154bb565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008282101561575057615750615728565b500390565b6020808252601590820152741cdd185d1d5cc8084f481a5b9a5d1a585b1a5e9959605a1b604082015260600190565b60006020828403121561579657600080fd5b815161125381614fb8565b600060033d11156157ba5760046000803e5060005160e01c5b90565b600060443d10156157cb5790565b6040516003193d81016004833e81513d6001600160401b0381602484011181841117156157fa57505050505090565b82850191508151818111156158125750505050505090565b843d870101602082850101111561582c5750505050505090565b61583b60208286010187615112565b509095945050505050565b602081526000611253602083018461526e565b6020808252601d908201527f4f776e61626c653a2073656e646572206d757374206265206f776e6572000000604082015260600190565b600082198211156158a3576158a3615728565b500190565b634e487b7160e01b600052603260045260246000fd5b6000808335601e198436030181126158d557600080fd5b8301803591506001600160401b038211156158ef57600080fd5b602001915036819003821315611dce57600080fd5b8183823760009101908152919050565b600060018060a01b03808b168352808a1660208401528860408401528088166060840152808716608084015260e060a08401528460e08401526101008587828601376000848701820152931660c083015250601f909201601f1916909101019695505050505050565b60006020828403121561598f57600080fd5b5051919050565b6000602082840312156159a857600080fd5b8151801515811461125357600080fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b60008083128015600160ff1b850184121615615a0257615a02615728565b6001600160ff1b0384018313811615615a1d57615a1d615728565b50500390565b634e487b7160e01b600052603160045260246000fd5b60008251615a4b818460208701615242565b9190910192915050565b600181815b80851115615a90578160001904821115615a7657615a76615728565b80851615615a8357918102915b93841c9390800290615a5a565b509250929050565b600082615aa7575060016107b5565b81615ab4575060006107b5565b8160018114615aca5760028114615ad457615af0565b60019150506107b5565b60ff841115615ae557615ae5615728565b50506001821b6107b5565b5060208310610133831016604e8410600b8410161715615b13575081810a6107b5565b615b1d8383615a55565b8060001904821115615b3157615b31615728565b029392505050565b600061125360ff841683615a9856fe8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046009acf4e54214992e70883cf7dcd6957ff2c71cd9e14df4bec4383bc0d11607dca264697066735822122071520f7a01fd7d370bd739d9cd965a8238fb4730007d5c800318f6424844443c64736f6c634300080c00330000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5dbc4edf467b609a063c7ea7fab976c6b9baa1a00000000000000000000000082900b0495303216d128d4770de425e0a3c14c1f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Deployed Bytecode
0x6080604052600436106102045760003560e01c8063a16594b911610118578063cc4aa204116100a0578063d3f44d841161006f578063d3f44d84146106bf578063d999ec8f146106df578063da60d637146106ff578063df4c96701461071f578063f23a6e611461074c57600080fd5b8063cc4aa20414610643578063d07041e014610677578063d2639b621461068c578063d26fef61146106ac57600080fd5b8063b670b058116100e7578063b670b05814610564578063ba728b5f14610584578063ba98d741146105a4578063bc12e3d7146105d1578063bc197c81146105fe57600080fd5b8063a16594b9146104c3578063ac9650d8146104e3578063ad5c464814610510578063b044ab751461054457600080fd5b80632d2c44f21161019b57806379e1aa381161016a57806379e1aa38146103e35780637a4f8d3a146103f65780637e28e8bf146104245780637f32cf41146104445780638df5db82146104a357600080fd5b80632d2c44f21461036757806357530e871461039b578063579e792f146103b0578063750f0acc146103c357600080fd5b806321651f8e116101d757806321651f8e146102bf57806327f39951146102f257806329390370146103275780632a0d3a291461034757600080fd5b806301ffc9a71461020957806307f3b8bb1461023e5780630cfd168f1461028a57806318f4a50a1461029f575b600080fd5b34801561021557600080fd5b50610229610224366004614ef2565b610778565b60405190151581526020015b60405180910390f35b34801561024a57600080fd5b506102727f000000000000000000000000e5dbc4edf467b609a063c7ea7fab976c6b9baa1a81565b6040516001600160a01b039091168152602001610235565b61029d610298366004614f38565b6107bb565b005b3480156102ab57600080fd5b5061029d6102ba366004614f6b565b6108a8565b3480156102cb57600080fd5b506102df6102da366004614f6b565b610be6565b604051600f9190910b8152602001610235565b3480156102fe57600080fd5b5061031261030d366004614f6b565b610c1f565b60408051928352602083019190915201610235565b34801561033357600080fd5b5061029d610342366004614f9d565b610c35565b34801561035357600080fd5b5061029d610362366004614fc7565b610d8f565b34801561037357600080fd5b506102727f00000000000000000000000082900b0495303216d128d4770de425e0a3c14c1f81565b3480156103a757600080fd5b506102df610ec0565b61029d6103be366004614ff6565b610ecf565b3480156103cf57600080fd5b5061029d6103de366004614f6b565b610fab565b61029d6103f136600461505d565b61111f565b34801561040257600080fd5b50610416610411366004614f6b565b611200565b604051908152602001610235565b34801561043057600080fd5b506102df61043f366004614f6b565b61120b565b34801561045057600080fd5b5061046461045f3660046150b9565b611241565b604051610235919081518152602080830151600f0b90820152604080830151908201526060918201516001600160a01b03169181019190915260800190565b3480156104af57600080fd5b5061029d6104be36600461513e565b61125a565b3480156104cf57600080fd5b506102df6104de366004614f6b565b611462565b3480156104ef57600080fd5b506105036104fe3660046151ce565b611493565b604051610235919061529a565b34801561051c57600080fd5b506102727f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab181565b34801561055057600080fd5b5061031261055f366004614f6b565b61159e565b34801561057057600080fd5b5061029d61057f3660046152fc565b611735565b34801561059057600080fd5b5061029d61059f366004614f6b565b611809565b3480156105b057600080fd5b506105c46105bf366004614f6b565b6118cd565b604051610235919061534d565b3480156105dd57600080fd5b506105f16105ec366004614f6b565b6118d8565b604051610235919061535b565b34801561060a57600080fd5b5061062a61061936600461552e565b63bc197c8160e01b95945050505050565b6040516001600160e01b03199091168152602001610235565b34801561064f57600080fd5b506102727f000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da181565b34801561068357600080fd5b506104166118e9565b34801561069857600080fd5b506104166106a7366004614f6b565b6118f3565b61029d6106ba3660046155d7565b61194b565b3480156106cb57600080fd5b5061029d6106da3660046150b9565b6119f8565b3480156106eb57600080fd5b5061029d6106fa366004614f9d565b611c62565b34801561070b57600080fd5b5061031261071a366004615616565b611dbc565b34801561072b57600080fd5b5061073f61073a366004614f9d565b611dd5565b6040516102359190615649565b34801561075857600080fd5b5061062a61076736600461568d565b63f23a6e6160e01b95945050505050565b6001600160e01b0319811660009081527f326d0c59a7612f6a9919e2a8ee333c80ba689d8ba2634de89c85cbb04832e705602052604081205460ff165b92915050565b600080516020615b698339815191528054600214156107f55760405162461bcd60e51b81526004016107ec906156f1565b60405180910390fd5b600281556000610803611e9b565b6001600160401b0386166000908152600282016020526040902090915061082981611ebf565b60008061083884848989611f09565b91509150600061084782611fbe565b905061088a3330610858848661573e565b6001600160a01b037f000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da11692919061217a565b61089985858b868c60006121e5565b50506001909355505050505050565b60006108b2611e9b565b6001600160401b0383166000908152600282016020526040902080549192509060ff1660048111156108e6576108e6615315565b6001146109055760405162461bcd60e51b81526004016107ec90615755565b6107088160030154610917919061573e565b421161095b5760405162461bcd60e51b815260206004820152601360248201527270726963652073657420746f6f206561726c7960681b60448201526064016107ec565b60018101546000600160801b909104600f0b131580610985575060018101546000600f9190910b13155b6109ca5760405162461bcd60e51b81526020600482015260166024820152751c1c9a58d95cc8185c9948185b1c9958591e481cd95d60521b60448201526064016107ec565b4281600301541115610bd7576000808360060160009054906101000a90046001600160a01b03166001600160a01b031663d33b48b56040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015610a4a575060408051601f3d908101601f19168201909252610a4791810190615784565b60015b610ac357610a566157a1565b806308c379a01415610ab75750610a6b6157bd565b80610a765750610ab9565b7fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab81604051610aa59190615846565b60405180910390a16000925050610ac6565b505b3d6000803e3d6000fd5b91505b60068401548354604051631d94c9b360e01b81526101009091046001600160401b031660048201526001600160a01b0390911690631d94c9b390602401602060405180830381865afa925050508015610b3c575060408051601f3d908101601f19168201909252610b3991810190615784565b60015b610ba957610b486157a1565b806308c379a01415610ab75750610b5d6157bd565b80610b685750610ab9565b7fcf34ef537ac33ee1ac626ca1587a0a7e8e51561e5514f8cb36afa1c5102b3bab81604051610b979190615846565b60405180910390a16000915050610bac565b90505b600082600f0b138015610bc25750600081600f0b135b15610bd457610bd484848785856122cb565b50505b610be181846125ca565b505050565b600080610bf1611e9b565b6001600160401b03841660009081526002820160205260409020909150610c1781612624565b949350505050565b600080610c2c833361269a565b91509150915091565b600080516020615b49833981519152546001600160a01b03163314610c6c5760405162461bcd60e51b81526004016107ec90615859565b6000610c76611e9b565b90506001600160a01b038216610cc55760405162461bcd60e51b81526020600482015260146024820152731859191c995cdcc81b9bdd081c1c9bdd9a59195960621b60448201526064016107ec565b60068101546001600160a01b0383811691161415610d1e5760405162461bcd60e51b81526020600482015260166024820152751b995dc81859191c995cdcc8195c5d585b1cc81bdb1960521b60448201526064016107ec565b6006810154604080516001600160a01b03928316815291841660208301523382820152517faa40df73b7e66d2e4e3a90deb47486303ca82739a96c5595ba8c68d00482fed29181900360600190a160060180546001600160a01b0319166001600160a01b0392909216919091179055565b600080516020615b49833981519152546001600160a01b03163314610dc65760405162461bcd60e51b81526004016107ec90615859565b6000610dd0611e9b565b9050600082600f0b13610e125760405162461bcd60e51b815260206004820152600a602482015269064656c7461203c3d20360b41b60448201526064016107ec565b68010000000000000000600f83900b12610e5a5760405162461bcd60e51b815260206004820152600960248201526864656c7461203e203160b81b60448201526064016107ec565b805460408051600f92830b81529184900b60208301523382820152517f8ade3304a9dbce06100c268f7f1f6e66c1627bf10e8a495977290d0625148eb99181900360600190a180546001600160801b0319166001600160801b0392909216919091179055565b6000610eca6126c2565b905090565b600080516020615b69833981519152805460021415610f005760405162461bcd60e51b81526004016107ec906156f1565b600281556000610f0e611e9b565b6001600160401b03861660009081526002820160205260409020909150610f34816126d5565b6000610f4183878761270a565b6005840154909150600090610f80906001600160a01b03168a7f000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da16127a9565b9050610f8d818333612a32565b610f9c84848a8a8a60016121e5565b50506001909255505050505050565b600080516020615b69833981519152805460021415610fdc5760405162461bcd60e51b81526004016107ec906156f1565b600281556000610fea611e9b565b6001600160401b0384166000908152600282016020526040902080549192509060ff16600481111561101e5761101e615315565b600314806110415750805460ff16600481111561103d5761103d615315565b6004145b61108d5760405162461bcd60e51b815260206004820181905260248201527f73746174757320213d2070726f636573736564207c7c2063616e63656c6c656460448201526064016107ec565b805460ff1660048111156110a3576110a3615315565b6003141561110c5760058101546110bd9062015180615890565b42101561110c5760405162461bcd60e51b815260206004820152601960248201527f686f6c6420706572696f6420686173206e6f7420656e6465640000000000000060448201526064016107ec565b6111168285612a90565b50506001905550565b600080516020615b698339815191528054600214156111505760405162461bcd60e51b81526004016107ec906156f1565b60028155600061115e611e9b565b6001600160401b0386166000908152600282016020526040902090915061118481611ebf565b60008061119384848989611f09565b600586015491935091506000906111d4906001600160a01b03168b7f000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da16127a9565b90506111e1818333612a32565b6111f085858b868c60006121e5565b5050600190935550505050505050565b60006107b582612c30565b600080611216611e9b565b6001600160401b03841660009081526002820160205260409020909150610c178160020154600f0b90565b611249614e04565b6112538383612c5f565b9392505050565b6000611264611e9b565b9050336001600160a01b037f00000000000000000000000082900b0495303216d128d4770de425e0a3c14c1f16146112c75760405162461bcd60e51b8152602060048201526006602482015265085d985d5b1d60d21b60448201526064016107ec565b60006112d1611e9b565b83516001600160401b031660009081526002820160205260408120919250815460ff16600481111561130557611305615315565b146113525760405162461bcd60e51b815260206004820152601760248201527f73746174757320213d20756e696e697469616c697a656400000000000000000060448201526064016107ec565b8360a00151846080015110158061136c5750836080015142115b80611383575083602001516001600160401b031642115b80611396575060008460400151600f0b13155b806113a357506060840151155b156113d45783516001600160401b03166000908152600283016020526040902084516113cf9190612ca2565b61145c565b6020840151815460408601516001600160801b0316600160481b0278ffffffffffffffffffffffffffffffff000000000000000000196001600160401b039093166101000292909216610100600160c81b0319909116171781556080840151600382015560a084015160048201556060840151600a820155835161145c908290600190612cb1565b50505050565b60008061146d611e9b565b6001600160401b03841660009081526002820160205260409020909150610c1781612d20565b6060816001600160401b038111156114ad576114ad6150fc565b6040519080825280602002602001820160405280156114e057816020015b60608152602001906001900390816114cb5790505b50905060005b828110156115975760008030868685818110611504576115046158a8565b905060200281019061151691906158be565b604051611524929190615904565b600060405180830381855af49150503d806000811461155f576040519150601f19603f3d011682016040523d82523d6000602084013e611564565b606091505b50915091508115610ab95780848481518110611582576115826158a8565b602002602001018190525050506001016114e6565b5092915050565b60008060006115ab611e9b565b9050336001600160a01b037f00000000000000000000000082900b0495303216d128d4770de425e0a3c14c1f161461160e5760405162461bcd60e51b8152602060048201526006602482015265085d985d5b1d60d21b60448201526064016107ec565b6000611618611e9b565b6001600160401b0386166000908152600282016020526040902080549192509060ff16600481111561164c5761164c615315565b6002146116915760405162461bcd60e51b81526020600482015260136024820152721cdd185d1d5cc8084f48199a5b985b1a5e9959606a1b60448201526064016107ec565b6116b081600701546116a78360020154600f0b90565b600f0b90612dd2565b6009820181905561170d906001600160a01b037f000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da116907f00000000000000000000000082900b0495303216d128d4770de425e0a3c14c1f90612e3a565b42600582015561171f81600388612cb1565b8060090154816007015494509450505050915091565b600080516020615b49833981519152546001600160a01b0316331461176c5760405162461bcd60e51b81526004016107ec90615859565b6000611776611e9b565b9050600082116117c05760405162461bcd60e51b815260206004820152601560248201527476616c75652065786365656473206d696e696d756d60581b60448201526064016107ec565b600181015460408051918252602082018490523382820152517f1f1913f02d98f08a2ed8c776d0559838fe3804f17663b57486c274065646ceb99181900360600190a160010155565b6000611813611e9b565b6001600160401b038316600090815260028201602052604090206004810154919250906118439062015180615890565b4211801561188557506001815460ff16600481111561186457611864615315565b148061188557506002815460ff16600481111561188357611883615315565b145b1561189457610be18184612ca2565b806003015442101580156118bd57506001815460ff1660048111156118bb576118bb615315565b145b15610be157610be1828285612e6a565b60006107b582612edc565b6118e0614e38565b6107b582612f0b565b6000610eca613019565b6000806118fe611e9b565b6001600160401b0384166000908152600282016020526040902060038101549192509015801590611933575080600301544210155b1561194157610c178461302c565b5060009392505050565b600080516020615b6983398151915280546002141561197c5760405162461bcd60e51b81526004016107ec906156f1565b60028155600061198a611e9b565b6001600160401b038616600090815260028201602052604090209091506119b0816126d5565b60006119bd83878761270a565b905060006119ca82611fbe565b90506119db3330610858848661573e565b6119ea84848a8a8a60016121e5565b505060019092555050505050565b600080516020615b69833981519152805460021415611a295760405162461bcd60e51b81526004016107ec906156f1565b600281556000611a37611e9b565b6001600160401b03851660009081526002820160205260409020909150611a5d816126d5565b6000846001600160801b031611611aa95760405162461bcd60e51b815260206004820152601060248201526f1a5b9d985b1a59081bdc99195c881a5960821b60448201526064016107ec565b6001600160401b0385166000908152600383016020526040812090611ad7826001600160801b03881661305b565b60608101519091506001600160a01b0316611b2b5760405162461bcd60e51b81526020600482015260146024820152731bdc99195c88191bd95cc81b9bdd08195e1a5cdd60621b60448201526064016107ec565b60608101516001600160a01b03163314611b7d5760405162461bcd60e51b8152602060048201526013602482015272313abcb2b910109e9036b9b39739b2b73232b960691b60448201526064016107ec565b611b90826001600160801b0388166130b4565b50611b9c848888613391565b82600301544210611bb257611bb2848489612e6a565b6000611bd282604001518360200151600f0b612dd290919063ffffffff16565b9050611c086001600160a01b037f000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da1163383612e3a565b604080516001600160801b03891681523360208201526001600160401b038a16917fb7a419a9cad0cf4a1610023a7ee67f873ba51a63189b14b543ee6f31db8b7f3c910160405180910390a2505060019093555050505050565b600080516020615b49833981519152546001600160a01b03163314611c995760405162461bcd60e51b81526004016107ec90615859565b6000611ca3611e9b565b90506001600160a01b038216611cf25760405162461bcd60e51b81526020600482015260146024820152731859191c995cdcc81b9bdd081c1c9bdd9a59195960621b60448201526064016107ec565b60058101546001600160a01b0383811691161415611d4b5760405162461bcd60e51b81526020600482015260166024820152751b995dc81859191c995cdcc8195c5d585b1cc81bdb1960521b60448201526064016107ec565b6005810154604080516001600160a01b03928316815291841660208301523382820152517f045d485de10addb86db6ce795700266572ef7d9132df09a384062b5e82a093739181900360600190a160050180546001600160a01b0319166001600160a01b0392909216919091179055565b600080611dc9848461269a565b915091505b9250929050565b60606000611de1611e9b565b6001600160a01b03841660009081526004820160205260408120919250611e078261344e565b6001600160401b03811115611e1e57611e1e6150fc565b604051908082528060200260200182016040528015611e47578160200160208202803683370190505b50905060005b611e568361344e565b811015611e92576000611e698483613458565b905080838381518110611e7e57611e7e6158a8565b602090810291909101015250600101611e4d565b50949350505050565b7f7f75137652cf01fd4e0a016c479a4a2bdc1018772b7fc0eab68410c366c40cbb90565b805460ff166004811115611ed557611ed5615315565b600114611ef45760405162461bcd60e51b81526004016107ec90615755565b611efd81613464565b611f06816134fa565b50565b6000808560010154841015611f515760405162461bcd60e51b815260206004820152600e60248201526d73697a65203c206d696e696d756d60901b60448201526064016107ec565b6000611f5c86612d20565b90506000611f6e600f83900b87612dd2565b905080851015611fb15760405162461bcd60e51b815260206004820152600e60248201526d18dbdcdd080f881b585e10dbdcdd60921b60448201526064016107ec565b9097909650945050505050565b60008034156107b5577f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b03167f000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da16001600160a01b03161461205d5760405162461bcd60e51b81526020600482015260126024820152710c6ded8d8c2e8cae4c2d840427a40ee8aa8960731b60448201526064016107ec565b823411156120fd57604051600090339034869003908381818185875af1925050503d80600081146120aa576040519150601f19603f3d011682016040523d82523d6000602084013e6120af565b606091505b50509050806120f45760405162461bcd60e51b8152602060048201526011602482015270115512081c99599d5b990819985a5b1959607a1b60448201526064016107ec565b83915050612100565b50345b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561215b57600080fd5b505af115801561216f573d6000803e3d6000fd5b505050505092915050565b6040516001600160a01b038085166024830152831660448201526064810182905261145c9085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261358c565b6001600160401b038416600090815260038701602052604081206122149061220f9086863361365e565b613808565b905060006122228683613865565b33600090815260048a016020526040902090915061224090826138a4565b508660030154421061225757612257888888612e6a565b604080516001600160801b0384168152336020820152600f87900b918101919091526060810185905283151560808201526001600160401b038716907f02270113c1297ab39d725cfb6962831ea118df963a68a6ce2fe974bef26954659060a0015b60405180910390a25050505050505050565b83548554600160481b909104600f90810b916000916122ec9184910b6138b0565b905060007f000000000000000000000000000000000000000000000000000000000000000061232857612323600f84900b836138e7565b612336565b612336600f84900b8361391a565b6006890154604051631b1aac9960e31b8152600f88810b600483015286810b602483015287900b60448201527f0000000000000000000000000000000000000000000000000000000000000000151560648201529192506001600160a01b03169063d8d564c890608401602060405180830381865afa1580156123bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123e19190615784565b6001880180546001600160801b0319166001600160801b03929092169190911790556006880154604051631b1aac9960e31b8152600f87810b600483015283810b602483015286900b60448201527f0000000000000000000000000000000000000000000000000000000000000000151560648201526001600160a01b039091169063d8d564c890608401602060405180830381865afa158015612489573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124ad9190615784565b6001880180546001600160801b03928316600160801b0292169190911790557f00000000000000000000000000000000000000000000000000000000000000001561255c57600187015461250490600f0b8661394d565b6001880180546001600160801b0319166001600160801b0392909216919091179081905561253c90600160801b9004600f0b8661394d565b6001880180546001600160801b03928316600160801b0292169190911790555b600187015460408051600f86810b825284810b602083015288810b9282019290925282820b6060820152600160801b909204900b60808201526001600160401b038716907f447e2e3d9b721c94b61250f439e96e626afd0552cb425d4c46da503a58096a779060a0016122b9565b60018201546000600f9190910b1315806125f4575060018201546000600160801b909104600f0b13155b8061261157506001820154600160801b8104600f90810b91900b13155b15612620576126208282612ca2565b5050565b60006002825460ff16600481111561263e5761263e615315565b148061265f57506003825460ff16600481111561265d5761265d615315565b145b8061267f57506004825460ff16600481111561267d5761267d615315565b145b15612691576002820154600f0b6107b5565b6107b582612d20565b60008060006126a7611e9b565b90506126b681600187876139a5565b92509250509250929050565b60006126cc611e9b565b54600f0b919050565b805460ff1660048111156126eb576126eb615315565b600114611efd5760405162461bcd60e51b81526004016107ec90615755565b60008083600f0b1361274b5760405162461bcd60e51b815260206004820152600a60248201526907072696365203c3d20360b41b60448201526064016107ec565b83600101548210156127905760405162461bcd60e51b815260206004820152600e60248201526d73697a65203c206d696e696d756d60901b60448201526064016107ec565b60006127a0600f85900b84612dd2565b95945050505050565b600034156128db576001600160a01b037f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1166127e86020850185614f9d565b6001600160a01b0316146128305760405162461bcd60e51b815260206004820152600f60248201526e0e8ded6cadc92dc40427a40ee8aa89608b1b60448201526064016107ec565b7f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab16001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561288b57600080fd5b505af115801561289f573d6000803e3d6000fd5b506128db9350506001600160a01b037f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab116915086905034612e3a565b60208301351561290c5761290c3385602086018035906128fb9088614f9d565b6001600160a01b031692919061217a565b60006001600160a01b038516632e25a7ab61292a6020870187614f9d565b856129393460208a0135615890565b61294960808a0160608b01614f9d565b61295960a08b0160808c01614f9d565b61296660a08c018c6158be565b61297660e08e0160c08f01614f9d565b6040518963ffffffff1660e01b8152600401612999989796959493929190615914565b6020604051808303816000875af11580156129b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129dc919061597d565b90508360400135811015610c175760405162461bcd60e51b815260206004820152601c60248201527f6e6f7420656e6f756768206f75747075742066726f6d2074726164650000000060448201526064016107ec565b81831115612a7957610be181612a48848661573e565b6001600160a01b037f000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da1169190612e3a565b82821115610be157610be18130610858868661573e565b600080612aa084600085336139a5565b91509150612ab084846000613391565b600080612abe868685613bb8565b915091508115612ae0578015612adb57612ad88185615890565b93505b600092505b8215612ba2576001600160401b0385166000908152600287016020526040808220600a01549051637921219560e11b815230600482015233602482015260448101919091526064810185905260a0608482015260a48101919091527f000000000000000000000000e5dbc4edf467b609a063c7ea7fab976c6b9baa1a6001600160a01b03169063f242432a9060c401600060405180830381600087803b158015612b8957600080fd5b505af1158015612b9d573d6000803e3d6000fd5b505050505b8315612bdc57612bdc6001600160a01b037f000000000000000000000000da10009cbd5d07dd0cecc66161fc93d7c9000da1163386612e3a565b60408051338152602081018690529081018490526001600160401b038616907f6c2dbbc7b415aab71b377f227d7a334f34899818306efbc6262b9ce85c4306be9060600160405180910390a2505050505050565b6000612c3a611e9b565b6001600160401b03909216600090815260029290920160205250604090206007015490565b612c67614e04565b6000612c71611e9b565b6001600160401b0385166000908152600391909101602052604090209050610c17816001600160801b03851661305b565b60006009830155612620826004835b82548290849060ff19166001836004811115612ccf57612ccf615315565b021790555082546040516001600160401b038316917f72d4affeac2e73f129f6fe359896ed8802d8bc11b826f9ac67cf50fcc7d3cc4d91612d139160ff169061534d565b60405180910390a2505050565b60038101546004820154600091908290612d3b90839061573e565b6001850154909150600f81810b91600160801b9004900b428410612d625750949350505050565b85600401544210612d765795945050505050565b6000612d82854261573e565b90506000612d908286613da8565b90506000612da2600f86900b856138e7565b90506000612db4600f84900b836138b0565b9050612dc4600f87900b826138e7565b9a9950505050505050505050565b600081612de1575060006107b5565b600083600f0b1215612df257600080fd5b600f83900b6001600160801b038316810260401c90608084901c026001600160c01b03811115612e2157600080fd5b60401b8119811115612e3257600080fd5b019392505050565b6040516001600160a01b038316602482015260448101829052610be190849063a9059cbb60e01b906064016121ae565b612e7482826125ca565b6004825460ff166004811115612e8c57612e8c615315565b14158015612ead5750612e9f8382613ddf565b80612ead5750816004015442115b15610be157600782015415612ed25760078201546008830155610be182600283612cb1565b610be18282612ca2565b6000612ee6611e9b565b6001600160401b03909216600090815260029290920160205250604090205460ff1690565b612f13614e38565b612f1b611e9b565b6001600160401b038316600090815260029190910160205260409081902081516101c081019092528054829060ff166004811115612f5b57612f5b615315565b6004811115612f6c57612f6c615315565b815281546101008082046001600160401b03166020840152600160481b909104600f90810b6040840152600184015480820b6060850152600160801b9004810b60808401526002840154900b60a0830152600383015460c0830152600483015460e08301526005830154908201526006820154610120820152600782015461014082015260088201546101608201526009820154610180820152600a909101546101a09091015292915050565b6000613023611e9b565b60010154905090565b6000613036611e9b565b6001600160401b03909216600090815260029290920160205250604090206006015490565b613063614e04565b506000908152600391820160209081526040918290208251608081018452815481526001820154600f0b928101929092526002810154928201929092529101546001600160a01b0316606082015290565b81546000908214156130cd576130ca8383613f45565b83555b6000828152600384016020526040812080548291829182919087146130fa576000955050505050506107b5565b600581015415158061310f5750600681015415155b156132cc5760058101541561314a578760030160006131358a84600001600001546141de565b81526020019081526020016000209450613172565b8760030160006131618a8460000160000154613f45565b815260200190815260200160002094505b6004850154600090815260038901602052604090208554600582015491955092508214156131ca57600685015460058501819055156131ca576006850154600090815260038901602052604090208454600482015592505b8454600685015414156132075760058501546006850181905515613207576005850154600090815260038901602052604090208454600482015592505b6004808201549086018190551561325f5760048101546000908152600389016020526040902081546005820154919550141561324557845460058501555b80546006850154141561325a57845460068501555b613267565b845460028901555b60058082015490860181905515613297576005810154600090815260038901602052604090208554600482015592505b600680820154908601819055156132c7576006810154600090815260038901602052604090208554600482015592505b613329565b6004810154156133215760048101546000908152600389016020526040902081546005820154919550141561330357600060058501555b80546006850154141561331857600060068501555b83549150613329565b600060028901555b60008082556001820180546001600160801b0319169055600282018190556003820180546001600160a01b031916905560048201819055600582018190556006820181905560078201558115613383576133838883614465565b506001979650505050505050565b3360009081526004840160205260408120905b6133ad8261344e565b8110156134475760006133c08383613458565b9050608081901c816001600160801b0386161580156133f05750866001600160401b0316826001600160401b0316145b806134285750856001600160801b0316816001600160801b03161480156134285750866001600160401b0316826001600160401b0316145b1561343957613437858461454c565b505b5050508060010190506133a4565b5050505050565b60006107b5825490565b60006112538383614558565b60008160030154116134b05760405162461bcd60e51b81526020600482015260156024820152741cdd185c9d081d1a5b59481a5cc81b9bdd081cd95d605a1b60448201526064016107ec565b8060030154421015611f065760405162461bcd60e51b8152602060048201526013602482015272185d58dd1a5bdb881b9bdd081cdd185c9d1959606a1b60448201526064016107ec565b60008160040154116135445760405162461bcd60e51b8152602060048201526013602482015272195b99081d1a5b59481a5cc81b9bdd081cd95d606a1b60448201526064016107ec565b8060040154421115611f065760405162461bcd60e51b8152602060048201526011602482015270185d58dd1a5bdb881a185cc8195b991959607a1b60448201526064016107ec565b60006135e1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166145de9092919063ffffffff16565b805190915015610be157808060200190518101906135ff9190615996565b610be15760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016107ec565b6000846001015460016136719190615890565b60018601819055855460009061368890889061305b565b602081015188549192509015806136a4575080600f0b87600f0b135b156136ad578288555b60008381526003890160205260409020548314156136fe576000838152600389016020526040902060010154600f88810b91900b14156136f257829350505050610c17565b6136fc88846130b4565b505b600088600201546000141561371557600289018490555b6002890154600090815260038a01602052604090205b805461378157848155600481018290556001810180546001600160801b0319166001600160801b038b16179055600281018890556003810180546001600160a01b0319166001600160a01b0389161790556137ed565b80546001820154909250600f90810b908a900b136137c35760068101546137aa57600681018590555b60060154600090815260038a016020526040902061372b565b60058101546137d457600581018590555b60050154600090815260038a016020526040902061372b565b80546137fa908b90614465565b509298975050505050505050565b60006001600160801b038211156138615760405162461bcd60e51b815260206004820152601c60248201527f53616665436173743a2076616c756520646f6573206e6f74206669740000000060448201526064016107ec565b5090565b60003060601b6001600160801b03831661389a67ffffffffffffffff60801b608087901b166001600160c01b03198416615890565b610c179190615890565b600061125383836145ed565b6000600f83810b9083900b0260401d60016001607f1b031981128015906138de575060016001607f1b038113155b61125357600080fd5b6000600f82810b9084900b0360016001607f1b031981128015906138de575060016001607f1b0381131561125357600080fd5b6000600f83810b9083900b0160016001607f1b031981128015906138de575060016001607f1b0381131561125357600080fd5b600081600f0b6000141561396057600080fd5b600082600f0b604085600f0b901b8161397b5761397b6159b8565b05905060016001607f1b031981128015906138de575060016001607f1b0381131561125357600080fd5b6001600160401b038216600090815260028501602090815260408083206003880190925282208291908280806139da85612624565b600886015490915060006139f66139ef875490565b879061305b565b90505b8051600090613a09908890613f45565b90508a6001600160a01b031682606001516001600160a01b03161415613b6157600080613a4a84604001518560200151600f0b612dd290919063ffffffff16565b905060048a5460ff166004811115613a6457613a64615315565b14158015613a725750600085115b8015613a88575085600f0b8460200151600f0b12155b15613b24576000613aa9856040015188600f0b612dd290919063ffffffff16565b90508585604001511115613ae457613ac5600f88900b87612dd2565b9050613ad18689615890565b9750613add8684615890565b9250613b08565b6040850151613af39089615890565b9750846040015183613b059190615890565b92505b613b12818361573e565b613b1c908a615890565b985050613b31565b613b2e8189615890565b97505b8e613b5e57818a6008016000828254613b4a919061573e565b90915550508351613b5c908a906130b4565b505b50505b8215613b8e578282604001511115613b7c5760009250613b8e565b6040820151613b8b908461573e565b92505b613b98878261305b565b8051909250151590506139f95750929b919a509098505050505050505050565b6001600160401b0380831660009081526002850160205260408120805491928392610100810490911690600160481b9004600f0b42821115613c035760008094509450505050613da0565b60405163098df99d60e11b81526001600160401b03831660048201526000907f000000000000000000000000e5dbc4edf467b609a063c7ea7fab976c6b9baa1a6001600160a01b03169063131bf33a90602401602060405180830381865afa158015613c73573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613c979190615784565b905060007f00000000000000000000000000000000000000000000000000000000000000008015613ccd575082600f0b82600f0b135b15613cf857613cf1886116a784613ce8600f82900b886138e7565b600f0b9061394d565b9050613d95565b7f0000000000000000000000000000000000000000000000000000000000000000158015613d2b575081600f0b83600f0b135b15613d95576000613d44896116a7600f87900b866138e7565b9050613d917f00000000000000000000000000000000000000000000000000000000000000127f00000000000000000000000000000000000000000000000000000000000000128361463c565b9150505b600196509450505050505b935093915050565b600081613db457600080fd5b6000613dc08484614659565b905060016001607f1b036001600160801b038216111561125357600080fd5b6001600160401b038116600090815260038301602090815260408083206002860190925282206006810154613e3f576000613e19826147bb565b905060008111613e3957613e2d8286612ca2565b600093505050506107b5565b60068201555b6000806000613e56613e4f865490565b869061305b565b90505b8051600090613e69908790613f45565b9050613e7485612624565b600f0b8260200151600f0b1215613e8b5750613f12565b60068501546040830151613e9f9086615890565b10613ee15750602001516002840180546001600160801b0319166001600160801b039092169190911790555050600681015460079091015550600190506107b5565b6040820151613ef09085615890565b60208301519094509250613f04868261305b565b805190925015159050613e59575b506002830180546001600160801b0319166001600160801b03929092169190911790556007909101555060009392505050565b600081815260038301602052604081208054613f655760009150506107b5565b613f6d614ebd565b60068201541561409a5750600680820154600090815260038087016020908152604092839020835161012081018552815460a082019081526001830154600f0b60c0830152600283015460e0830152938201546001600160a01b03166101008201529283526004810154918301919091526005810154928201929092529181015460608301526007015460808201525b60408101511561408f5760409081015160009081526003808701602090815291839020835161012081018552815460a082019081526001830154600f0b60c0830152600283015460e0830152928201546001600160a01b031661010082015291825260048101549282019290925260058201549281019290925260068101546060830152600701546080820152613ffd565b515191506107b59050565b6004820154156141d357506004810154600081815260038087016020908152604092839020835161012081018552865460a082019081526001880154600f0b60c0830152600288015460e0830152938701546001600160a01b0316610100820152928352908201939093526005840154918101919091526006830154606082015260078301546080820152905b81515160058201541415614140575492506107b5915050565b600481015461414e576141d1565b6040805161012081018252825460a082019081526001840154600f0b60c0830152600284015460e08301526003808501546001600160a01b03166101008401529082526004840154602080840182905260058601548486015260068601546060850152600790950154608084015260009081529089019093529120909150614127565b505b506000949350505050565b6000818152600383016020526040812080546141fe5760009150506107b5565b614206614ebd565b60058201541561432e5750600580820154600090815260038087016020908152604092839020835161012081018552815460a082019081526001830154600f0b60c0830152600283015460e0830152938201546001600160a01b031661010082015292835260048101549183019190915292830154918101919091526006820154606082015260079091015460808201525b60608101511561408f57606090810151600090815260038087016020908152604092839020835161012081018552815460a082019081526001830154600f0b60c0830152600283015460e0830152938201546001600160a01b0316610100820152928352600481015491830191909152600581015492820192909252600682015492810192909252600701546080820152614298565b6004820154156141d357506004810154600081815260038087016020908152604092839020835161012081018552865460a082019081526001880154600f0b60c0830152600288015460e0830152938701546001600160a01b0316610100820152928352908201939093526005840154918101919091526006830154606082015260078301546080820152905b815151600682015414156143d4575492506107b5915050565b60048101546143e2576141d1565b6040805161012081018252825460a082019081526001840154600f0b60c0830152600284015460e08301526003808501546001600160a01b031661010084015290825260048401546020808401829052600586015484860152600686015460608501526007909501546080840152600090815290890190935291209091506143bb565b600081815260038301602052604090205b805460009061448690859061493c565b905080600214156144c35761449f84836005015461493c565b60001914156144b6576144b6848360050154614974565b81546144c3908590614a68565b8060011914156144fe576144db84836006015461493c565b600114156144f1576144f1848360060154614a68565b81546144fe908590614974565b8060001913158015614511575060018113155b15614523578154614523908590614b4b565b60048201546145325750505050565b506004015460009081526003830160205260409020614476565b60006112538383614b9a565b815460009082106145b65760405162461bcd60e51b815260206004820152602260248201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604482015261647360f01b60648201526084016107ec565b8260000182815481106145cb576145cb6158a8565b9060005260206000200154905092915050565b6060610c178484600085614c67565b6000818152600183016020526040812054614634575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556107b5565b5060006107b5565b6000806146498386614d67565b90506127a0600f82900b85614d7d565b60008161466557600080fd5b60006001600160c01b0384116146905782604085901b81614688576146886159b8565b0490506147a7565b60c084811c64010000000081106146a9576020918201911c5b6201000081106146bb576010918201911c5b61010081106146cc576008918201911c5b601081106146dc576004918201911c5b600481106146ec576002918201911c5b600281106146fb576001820191505b60bf820360018603901c6001018260ff0387901b8161471c5761471c6159b8565b0492506001600160801b0383111561473357600080fd5b608085901c83026001600160801b038616840260c088901c604089901b8281101561475f576001820391505b608084901b92900382811015614776576001820391505b829003608084901c821461478c5761478c6159ce565b88818161479b5761479b6159b8565b04870196505050505050505b6001600160801b0381111561125357600080fd5b6000807f00000000000000000000000082900b0495303216d128d4770de425e0a3c14c1f6001600160a01b0316634ac8eb5f6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561481c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614840919061597d565b905060007f00000000000000000000000082900b0495303216d128d4770de425e0a3c14c1f6001600160a01b031663a19471196040518163ffffffff1660e01b8152600401602060405180830381865afa1580156148a2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906148c6919061597d565b90508082116148d6576000610c17565b8354610c17907f0000000000000000000000000000000000000000000000000000000000000000907f000000000000000000000000000000000000000000000000000000000000001290600160481b9004600f0b614934858761573e565b929190614d98565b6000818152600383016020526040808220600681015483528183206007908101546005830154855292842001549091610c17916159e4565b60008181526003830160205260409020600681015461499257600080fd5b6006810180546000908152600385016020526040812060048085015490820181905591909255156149fe576004820154600090815260038501602052604090208254600582015414156149e757815460058201555b8254600682015414156149fc57815460068201555b505b600581015415614a2d576005810154600090815260038501602052604090208054600684015582546004909101555b805460048084019190915582546005830155810154614a4e57805460028501555b8154614a5b908590614b4b565b805461145c908590614b4b565b600081815260038301602052604090206005810154614a8657600080fd5b600581018054600090815260038501602052604081206004808501549082018190559190925515614af257600482015460009081526003850160205260409020825460058201541415614adb57815460058201555b825460068201541415614af057815460068201555b505b600681015415614b2257600681015460008181526003860160205260409020600584019190915582546004909101555b805460048084019190915582546006830155810154614a4e57805460028501558154614a5b9085905b600081815260038301602052604080822060058101548352818320600790810154600683015485529290932090920154614b859190614dee565b614b90906001615890565b6007909101555050565b60008181526001830160205260408120548015614c5d57835460009085906000198101908110614bcc57614bcc6158a8565b9060005260206000200154905080856000016001840381548110614bf257614bf26158a8565b6000918252602080832090910192909255918252600186019052604090208190558354849080614c2457614c24615a23565b600190038181906000526020600020016000905590558360010160008481526020019081526020016000206000905560019150506107b5565b60009150506107b5565b6060843b614ccb5760405162461bcd60e51b815260206004820152602b60248201527f416464726573735574696c733a2066756e6374696f6e2063616c6c20746f206e60448201526a1bdb8b58dbdb9d1c9858dd60aa1b60648201526084016107ec565b600080866001600160a01b03168587604051614ce79190615a39565b60006040518083038185875af1925050503d8060008114614d24576040519150601f19603f3d011682016040523d82523d6000602084013e614d29565b606091505b50915091508115614d3d579150610c179050565b805115614d4d5780518082602001fd5b8360405162461bcd60e51b81526004016107ec9190615846565b600061125383614d7884600a615b39565b613da8565b6000611253614d8d83600a615b39565b600f85900b90612dd2565b600081600f0b60001415614dae57506000610c17565b8315614dbb575083610c17565b6000614dc78685614d67565b9050614de484614ddb600f84900b8661394d565b600f0b90614d7d565b9695505050505050565b6000818310614dfe5750816107b5565b50919050565b6040518060800160405280600081526020016000600f0b81526020016000815260200160006001600160a01b031681525090565b604080516101c08101909152806000815260200160006001600160401b031681526020016000600f0b81526020016000600f0b81526020016000600f0b81526020016000600f0b815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b6040518060a00160405280614ed0614e04565b8152602001600081526020016000815260200160008152602001600081525090565b600060208284031215614f0457600080fd5b81356001600160e01b03198116811461125357600080fd5b80356001600160401b0381168114614f3357600080fd5b919050565b600080600060608486031215614f4d57600080fd5b614f5684614f1c565b95602085013595506040909401359392505050565b600060208284031215614f7d57600080fd5b61125382614f1c565b80356001600160a01b0381168114614f3357600080fd5b600060208284031215614faf57600080fd5b61125382614f86565b80600f0b8114611f0657600080fd5b600060208284031215614fd957600080fd5b813561125381614fb8565b600060e08284031215614dfe57600080fd5b6000806000806080858703121561500c57600080fd5b84356001600160401b0381111561502257600080fd5b61502e87828801614fe4565b94505061503d60208601614f1c565b9250604085013561504d81614fb8565b9396929550929360600135925050565b6000806000806080858703121561507357600080fd5b84356001600160401b0381111561508957600080fd5b61509587828801614fe4565b9450506150a460208601614f1c565b93969395505050506040820135916060013590565b600080604083850312156150cc57600080fd5b6150d583614f1c565b915060208301356001600160801b03811681146150f157600080fd5b809150509250929050565b634e487b7160e01b600052604160045260246000fd5b601f8201601f191681016001600160401b0381118282101715615137576151376150fc565b6040525050565b600060c0828403121561515057600080fd5b60405160c081018181106001600160401b0382111715615172576151726150fc565b60405261517e83614f1c565b815261518c60208401614f1c565b6020820152604083013561519f81614fb8565b80604083015250606083013560608201526080830135608082015260a083013560a08201528091505092915050565b600080602083850312156151e157600080fd5b82356001600160401b03808211156151f857600080fd5b818501915085601f83011261520c57600080fd5b81358181111561521b57600080fd5b8660208260051b850101111561523057600080fd5b60209290920196919550909350505050565b60005b8381101561525d578181015183820152602001615245565b8381111561145c5750506000910152565b60008151808452615286816020860160208601615242565b601f01601f19169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b828110156152ef57603f198886030184526152dd85835161526e565b945092850192908501906001016152c1565b5092979650505050505050565b60006020828403121561530e57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6005811061534957634e487b7160e01b600052602160045260246000fd5b9052565b602081016107b5828461532b565b60006101c08201905061536f82845161532b565b602083015161538960208401826001600160401b03169052565b50604083015161539e6040840182600f0b9052565b5060608301516153b36060840182600f0b9052565b5060808301516153c86080840182600f0b9052565b5060a08301516153dd60a0840182600f0b9052565b5060c0838101519083015260e08084015190830152610100808401519083015261012080840151908301526101408084015190830152610160808401519083015261018080840151908301526101a092830151929091019190915290565b600082601f83011261544c57600080fd5b813560206001600160401b03821115615467576154676150fc565b8160051b60405161547a83830182615112565b9283528481018201928281018785111561549357600080fd5b83870192505b848310156154b05782358152918301918301615499565b509695505050505050565b600082601f8301126154cc57600080fd5b81356001600160401b038111156154e5576154e56150fc565b6040516154fc601f8301601f191660200182615112565b81815284602083860101111561551157600080fd5b816020850160208301376000918101602001919091529392505050565b600080600080600060a0868803121561554657600080fd5b61554f86614f86565b945061555d60208701614f86565b935060408601356001600160401b038082111561557957600080fd5b61558589838a0161543b565b9450606088013591508082111561559b57600080fd5b6155a789838a0161543b565b935060808801359150808211156155bd57600080fd5b506155ca888289016154bb565b9150509295509295909350565b6000806000606084860312156155ec57600080fd5b6155f584614f1c565b9250602084013561560581614fb8565b929592945050506040919091013590565b6000806040838503121561562957600080fd5b61563283614f1c565b915061564060208401614f86565b90509250929050565b6020808252825182820181905260009190848201906040850190845b8181101561568157835183529284019291840191600101615665565b50909695505050505050565b600080600080600060a086880312156156a557600080fd5b6156ae86614f86565b94506156bc60208701614f86565b9350604086013592506060860135915060808601356001600160401b038111156156e557600080fd5b6155ca888289016154bb565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b634e487b7160e01b600052601160045260246000fd5b60008282101561575057615750615728565b500390565b6020808252601590820152741cdd185d1d5cc8084f481a5b9a5d1a585b1a5e9959605a1b604082015260600190565b60006020828403121561579657600080fd5b815161125381614fb8565b600060033d11156157ba5760046000803e5060005160e01c5b90565b600060443d10156157cb5790565b6040516003193d81016004833e81513d6001600160401b0381602484011181841117156157fa57505050505090565b82850191508151818111156158125750505050505090565b843d870101602082850101111561582c5750505050505090565b61583b60208286010187615112565b509095945050505050565b602081526000611253602083018461526e565b6020808252601d908201527f4f776e61626c653a2073656e646572206d757374206265206f776e6572000000604082015260600190565b600082198211156158a3576158a3615728565b500190565b634e487b7160e01b600052603260045260246000fd5b6000808335601e198436030181126158d557600080fd5b8301803591506001600160401b038211156158ef57600080fd5b602001915036819003821315611dce57600080fd5b8183823760009101908152919050565b600060018060a01b03808b168352808a1660208401528860408401528088166060840152808716608084015260e060a08401528460e08401526101008587828601376000848701820152931660c083015250601f909201601f1916909101019695505050505050565b60006020828403121561598f57600080fd5b5051919050565b6000602082840312156159a857600080fd5b8151801515811461125357600080fd5b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052600160045260246000fd5b60008083128015600160ff1b850184121615615a0257615a02615728565b6001600160ff1b0384018313811615615a1d57615a1d615728565b50500390565b634e487b7160e01b600052603160045260246000fd5b60008251615a4b818460208701615242565b9190910192915050565b600181815b80851115615a90578160001904821115615a7657615a76615728565b80851615615a8357918102915b93841c9390800290615a5a565b509250929050565b600082615aa7575060016107b5565b81615ab4575060006107b5565b8160018114615aca5760028114615ad457615af0565b60019150506107b5565b60ff841115615ae557615ae5615728565b50506001821b6107b5565b5060208310610133831016604e8410600b8410161715615b13575081810a6107b5565b615b1d8383615a55565b8060001904821115615b3157615b31615728565b029392505050565b600061125360ff841683615a9856fe8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046009acf4e54214992e70883cf7dcd6957ff2c71cd9e14df4bec4383bc0d11607dca264697066735822122071520f7a01fd7d370bd739d9cd965a8238fb4730007d5c800318f6424844443c64736f6c634300080c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000e5dbc4edf467b609a063c7ea7fab976c6b9baa1a00000000000000000000000082900b0495303216d128d4770de425e0a3c14c1f00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
-----Decoded View---------------
Arg [0] : isCall (bool): False
Arg [1] : pool (address): 0xE5DbC4EDf467B609A063c7ea7fAb976C6b9BAa1a
Arg [2] : vault (address): 0x82900b0495303216d128d4770de425E0a3c14C1f
Arg [3] : weth (address): 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [1] : 000000000000000000000000e5dbc4edf467b609a063c7ea7fab976c6b9baa1a
Arg [2] : 00000000000000000000000082900b0495303216d128d4770de425e0a3c14c1f
Arg [3] : 00000000000000000000000082af49447d8a07e3bd95bd0d56f35241523fbab1
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.