Source Code
Overview
FRAX Balance | FXTL Balance
0 FRAX | 0 FXTL
FRAX Value
$0.00| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 1473619 | 690 days ago | Contract Creation | 0 FRAX |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
SlippageAuction
Compiler Version
v0.8.24+commit.e11b9ed9
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: ISC
pragma solidity ^0.8.23;
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ========================= SlippageAuction ==========================
// ====================================================================
// Dutch-style Auction. Starts at a high price and gradually decreases until the entire lot
// of tokens is sold, or the time expires.
// Frax Finance: https://github.com/FraxFinance
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import { IERC20, IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import { Timelock2Step } from "frax-std/access-control/v2/Timelock2Step.sol";
import { IUniswapV2Callee } from "./interfaces/IUniswapV2Callee.sol";
/// @title SlippageAuction
/// @notice Slippage auction to sell tokens over time. Created via factory.
/// @dev Both tokens must be 18 decimals.
/// @dev https://github.com/FraxFinance/frax-bonds
contract SlippageAuction is ReentrancyGuard, Timelock2Step {
using SafeERC20 for IERC20;
// ==============================================================================
// Storage
// ==============================================================================
/// @notice The name of this auction
string public name;
/// @notice Slippage precision
uint256 public constant PRECISION = 1e18;
/// @notice Stored information about details
Detail[] public details;
/// @notice The token used for buying the tokenSell
address public immutable TOKEN_BUY;
/// @notice The token being auctioned off
address public immutable TOKEN_SELL;
/// @notice Alias for TOKEN_BUY
/// @dev Maintains UniswapV2 interface
address public immutable token0;
/// @notice Alias for TOKEN_SELL
/// @notice Maintains UniswapV2 interface
address public immutable token1;
// ==============================================================================
// Structs
// ==============================================================================
/// @notice Detail information behind an auction
/// @notice Auction information
/// @param amountListed Amount of sellToken placed for auction
/// @param amountLeft Amount of sellToken remaining to buy
/// @param amountExcessBuy Amount of any additional TOKEN_BUY sent to contract during auction
/// @param amountExcessSell Amount of any additional TOKEN_SELL sent to contract during auction
/// @param tokenBuyReceived Amount of tokenBuy that came in from sales
/// @param priceLast Price of the last sale, in tokenBuy amount per tokenSell (amount of tokenBuy to purchase 1e18 tokenSell)
/// @param priceMin Minimum price of 1e18 tokenSell, in tokenBuy
/// @param priceDecay Price decay, (wei per second), using PRECISION
/// @param priceSlippage Slippage fraction. E.g (0.01 * PRECISION) = 1%
/// @param lastBuyTime Time of the last sale
/// @param expiry UNIX timestamp when the auction ends
/// @param active If the auction is active
struct Detail {
uint128 amountListed;
uint128 amountLeft;
uint128 amountExcessBuy;
uint128 amountExcessSell;
uint128 tokenBuyReceived;
uint128 priceLast;
uint128 priceMin;
uint64 priceDecay;
uint64 priceSlippage;
uint32 lastBuyTime;
uint32 expiry;
bool active;
}
// ==============================================================================
// Constructor
// ==============================================================================
/// @param _timelock Address of the timelock/owner
/// @param _tokenBuy Token used to purchase _tokenSell
/// @param _tokenSell Token sold in the auction
constructor(address _timelock, address _tokenBuy, address _tokenSell) Timelock2Step(_timelock) {
name = string(abi.encodePacked("SlippageAuction: ", IERC20Metadata(_tokenSell).symbol()));
TOKEN_BUY = _tokenBuy;
TOKEN_SELL = _tokenSell;
token0 = _tokenBuy;
token1 = _tokenSell;
}
// ==============================================================================
// Views
// ==============================================================================
/// @notice Returns the semantic version of this contract
/// @return _major The major version
/// @return _minor The minor version
/// @return _patch The patch version
function version() external pure returns (uint256 _major, uint256 _minor, uint256 _patch) {
return (1, 0, 1);
}
/// @notice Calculates the pre-slippage price (with the user supplied auction _detail) from the time decay alone
/// @param _detail The auction struct
/// @return _price The price
function getPreSlippagePrice(Detail memory _detail) public view returns (uint256 _price) {
// Calculate Decay
uint256 _decay = (_detail.priceDecay * (block.timestamp - _detail.lastBuyTime));
// Calculate the sale price (in tokenBuy per tokenSell), factoring in the time decay
if (_detail.priceLast < _decay) {
return _price = _detail.priceMin;
} else {
_price = _detail.priceLast - _decay;
}
// Never go below the minimum price
if (_price < _detail.priceMin) _price = _detail.priceMin;
}
/// @notice Calculates the pre-slippage price (with the current auction) from the time decay alone
function getPreSlippagePrice() external view returns (uint256) {
return getPreSlippagePrice(details[details.length - 1]);
}
/// @notice Calculates the amount of tokenSells out for a given tokenBuy amount
/// @param amountIn Amount of tokenBuy in
/// @param _revertOnOverAmountLeft Whether to revert if amountOut > amountLeft
/// @return amountOut Amount of tokenSell out
/// @return _slippagePerTokenSell The slippage component of the price change (in tokenBuy per tokenSell)
/// @return _postPriceSlippage The post-slippage price from the time decay + slippage
function getAmountOut(
uint256 amountIn,
bool _revertOnOverAmountLeft
) public view returns (uint256 amountOut, uint256 _slippagePerTokenSell, uint256 _postPriceSlippage) {
// Get the auction number
uint256 _auctionNumber = details.length - 1;
// Get the auction info
Detail memory _detail = details[_auctionNumber];
// Revert if the auction is inactive or expired
if (!_detail.active) revert AuctionNotActive();
if (block.timestamp >= _detail.expiry) revert AuctionExpired();
// Calculate the sale price (in tokenBuy per tokenSell), factoring in the time decay
uint256 _preSlippagePrice = getPreSlippagePrice({ _detail: _detail });
// Calculate the slippage component of the price (in tokenBuy per tokenSell)
_slippagePerTokenSell = (_detail.priceSlippage * amountIn) / PRECISION;
// Calculate the output amount of tokenSell
amountOut = (amountIn * PRECISION) / (_preSlippagePrice + _slippagePerTokenSell);
// Make sure you are not going over the amountLeft
if (amountOut > _detail.amountLeft) {
if (_revertOnOverAmountLeft) revert InsufficientTokenSellsAvailable();
else amountOut = _detail.amountLeft;
}
// Set return value
_postPriceSlippage = _preSlippagePrice + (2 * _slippagePerTokenSell); // Price impact is twice the slippage
}
/// @notice Calculates how much tokenBuy you would need to buy out the remaining tokenSell in the auction
/// @return amountIn Amount of tokenBuy needed
/// @return _slippagePerTokenSell The slippage component of the price change (in tokenBuy per tokenSell)
/// @return _postPriceSlippage The post-slippage price from the time decay + slippage
function getAmountInMax()
external
view
returns (uint256 amountIn, uint256 _slippagePerTokenSell, uint256 _postPriceSlippage)
{
// Get the auction number
uint256 _auctionNumber = details.length - 1;
// Get the auction info
Detail memory detail = details[_auctionNumber];
// Call the internal function with amountLeft
return _getAmountIn({ _detail: detail, amountOut: detail.amountLeft });
}
/// @notice Calculates how much tokenBuy you would need in order to obtain a given number of tokenSell
/// @param amountOut The desired amount of tokenSell
/// @return amountIn Amount of tokenBuy needed
/// @return _slippagePerTokenSell The slippage component of the price change (in tokenBuy per tokenSell)
/// @return _postPriceSlippage The post-slippage price from the time decay + slippage
function getAmountIn(
uint256 amountOut
) public view returns (uint256 amountIn, uint256 _slippagePerTokenSell, uint256 _postPriceSlippage) {
// Get the auction number
uint256 _auctionNumber = details.length - 1;
// Get the auction info
Detail memory detail = details[_auctionNumber];
// Call the internal function with amountOut, set return values
(amountIn, _slippagePerTokenSell, _postPriceSlippage) = _getAmountIn({ _detail: detail, amountOut: amountOut });
}
/// @notice Calculate how much tokenBuy you would need to obtain a given number of tokenSell
/// @param _detail The auction struct
/// @return amountIn Amount of tokenBuy needed
/// @return _slippagePerTokenSell The slippage component of the price change (in tokenBuy per tokenSell)
/// @return _postPriceSlippage The post-slippage price from the time decay + slippage
function _getAmountIn(
Detail memory _detail,
uint256 amountOut
) internal view returns (uint256 amountIn, uint256 _slippagePerTokenSell, uint256 _postPriceSlippage) {
// Do checks
if (!_detail.active) revert AuctionNotActive();
if (block.timestamp >= _detail.expiry) revert AuctionExpired();
if (amountOut > _detail.amountLeft) revert InsufficientTokenSellsAvailable();
// Calculate the sale price (in tokenBuy per tokenSell), factoring in the time decay
uint256 _preSlippagePrice = getPreSlippagePrice({ _detail: _detail });
// Math in a more readable format:
// uint256 _numerator = (amountOut * _preSlippagePrice) / PRECISION;
// uint256 _denominator = (PRECISION -
// ((amountOut * uint256(_detail.priceSlippage)) / PRECISION));
// amountIn = (_numerator * PRECISION) / _denominator;
// Set return params amountIn
amountIn =
(amountOut * _preSlippagePrice) /
(PRECISION - (amountOut * uint256(_detail.priceSlippage)) / PRECISION);
// Set return params, calculate the slippage component of the price (in tokenBuy per tokenSell)
_slippagePerTokenSell = (_detail.priceSlippage * amountIn) / PRECISION;
_postPriceSlippage = _preSlippagePrice + (2 * _slippagePerTokenSell); // Price impact is twice the slippage
}
/// @notice Calculates how much tokenBuy you would need in order to obtain a given number of tokenSell
/// @dev Maintains compatibility with some router implementations
/// @param amountOut The amount out of sell tokens
/// @param tokenOut The sell token address
/// @return amountIn The amount of tokenBuy needed
function getAmountIn(uint256 amountOut, address tokenOut) public view returns (uint256 amountIn) {
if (tokenOut != TOKEN_SELL) revert InvalidTokenOut();
(amountIn, , ) = getAmountIn({ amountOut: amountOut });
}
/// @notice Calculates the amount of tokenSell out for a given tokenBuy amount
/// @dev Used to maintain compatibility
/// @param amountIn Amount of tokenBuy in
/// @param tokenIn The token being swapped in
/// @return amountOut Amount of tokenSells out
function getAmountOut(uint256 amountIn, address tokenIn) public view returns (uint256 amountOut) {
if (tokenIn != TOKEN_BUY) revert InvalidTokenIn();
(amountOut, , ) = getAmountOut({ amountIn: amountIn, _revertOnOverAmountLeft: false });
}
/// @dev Uni v2 support without revert
function skim(address) external pure {
return;
}
/// @dev Uni v2 support without revert
function sync() external pure {
return;
}
function getAmountOut(uint256, uint256, uint256) external pure returns (uint256) {
revert NotImplemented();
}
function getAmountIn(uint256, uint256, uint256) external pure returns (uint256) {
revert NotImplemented();
}
function getReserves() external pure returns (uint112, uint112, uint32) {
revert NotImplemented();
}
function price0CumulativeLast() external pure returns (uint256) {
revert NotImplemented();
}
function price1CumulativeLast() external pure returns (uint256) {
revert NotImplemented();
}
function kLast() external pure returns (uint256) {
revert NotImplemented();
}
function factory() external pure returns (address) {
revert NotImplemented();
}
function MINIMUM_LIQUIDITY() external pure returns (uint256) {
revert NotImplemented();
}
function initialize(address, address) external pure {
revert NotImplemented();
}
/// @notice Gets a struct instead of a tuple for details()
/// @param _auctionNumber Detail ID
/// @return The struct of the auction
function getDetailStruct(uint256 _auctionNumber) external view returns (Detail memory) {
return details[_auctionNumber];
}
/// @notice Returns the length of the details array
/// @return _length The length of the details array
function detailsLength() external view returns (uint256 _length) {
_length = details.length;
}
/// @notice Returns the latest auction
/// @dev Returns an empty struct if there are no auctions
/// @return _latestAuction The latest auction struct
function getLatestAuction() external view returns (Detail memory _latestAuction) {
uint256 _length = details.length;
if (_length == 0) return _latestAuction;
_latestAuction = details[details.length - 1];
}
// ==============================================================================
// Owner-only Functions
// ==============================================================================
/// @notice Parameters for starting an auction
/// @dev Sender must have an allowance on tokenSell
/// @param amountListed Amount of tokenSell being sold
/// @param priceStart Starting price of 1e18 tokenSell, in tokenBuy
/// @param priceMin Minimum price of 1e18 tokenSell, in tokenBuy
/// @param priceDecay Price decay, (wei per second), using PRECISION
/// @param priceSlippage Slippage fraction. E.g (0.01 * PRECISION) = 1%
/// @param expiry UNIX timestamp when the auction ends
struct StartAuctionParams {
uint128 amountListed;
uint128 priceStart;
uint128 priceMin;
uint64 priceDecay;
uint64 priceSlippage;
uint32 expiry;
}
/// @notice Starts a new auction
/// @dev Requires an ERC20 allowance on the tokenSell prior to calling
/// @param _params StartAuctionParams
function startAuction(StartAuctionParams calldata _params) external nonReentrant returns (uint256 _auctionNumber) {
_requireSenderIsTimelock();
// Check expiry is not in the past
if (_params.expiry < block.timestamp) revert Expired();
// Ensure that enough amountListed are for sale to prevent round-down errors
// see E2E test for 1e6 requirement. At 1e8 requirement, there should be enough trades
// to constitute an auction.
if (_params.amountListed < 1e8) revert AmountListedTooLow();
// Ensure that priceStart > priceMin
if (_params.priceStart < _params.priceMin) revert PriceStartLessThanPriceMin();
// Prevent edge-case revert of amountOut within getAmountOut
if (_params.priceMin == 0 && _params.priceSlippage == 0) revert PriceMinAndSlippageBothZero();
// Pre-compute the auction number
_auctionNumber = details.length;
// Ensure that the previous auction, if any, has been stopped
if (_auctionNumber > 0) {
Detail memory _lastAuction = details[_auctionNumber - 1];
if (_lastAuction.active) revert LastAuctionStillActive();
}
// Create the auction
details.push(
Detail({
amountListed: _params.amountListed,
amountLeft: _params.amountListed,
amountExcessBuy: 0,
amountExcessSell: 0,
tokenBuyReceived: 0,
priceLast: _params.priceStart,
priceMin: _params.priceMin,
priceDecay: _params.priceDecay,
priceSlippage: _params.priceSlippage,
lastBuyTime: uint32(block.timestamp),
expiry: _params.expiry,
active: true
})
);
emit AuctionStarted({
auctionNumber: _auctionNumber,
amountListed: _params.amountListed,
priceStart: _params.priceStart,
priceMin: _params.priceMin,
priceDecay: _params.priceDecay,
priceSlippage: _params.priceSlippage,
expiry: _params.expiry
});
// Clear out any tokens held by the auction so that bookkeeping is accurate
_withdrawAnyAvailableTokens({ _excess: true });
// Take the tokenSells from the sender
IERC20(TOKEN_SELL).safeTransferFrom(msg.sender, address(this), _params.amountListed);
}
/// @notice Ends the auction
/// @dev Only callable by the auction owner
/// @return tokenBuyReceived Amount of tokenBuy obtained from the auction
/// @return tokenSellRemaining Amount of unsold tokenSell left over
function stopAuction() public nonReentrant returns (uint256 tokenBuyReceived, uint256 tokenSellRemaining) {
_requireSenderIsTimelock();
// Get the auction info and perform checks
uint256 _auctionNumber = details.length - 1;
Detail storage detail = details[_auctionNumber];
if (!detail.active) revert AuctionNotActive();
// Skim excess token to sender if additional has been received to keep bookkeeping accurate
_withdrawIfTokenBalance({ _token: TOKEN_BUY, _priorBalance: detail.tokenBuyReceived, _excess: true });
_withdrawIfTokenBalance({ _token: TOKEN_SELL, _priorBalance: detail.amountLeft, _excess: true });
// Set Return params
tokenBuyReceived = IERC20(TOKEN_BUY).balanceOf(address(this));
tokenSellRemaining = IERC20(TOKEN_SELL).balanceOf(address(this));
// Effects: Update state with final balances;
detail.active = false;
detail.tokenBuyReceived = uint128(tokenBuyReceived);
detail.amountLeft = uint128(tokenSellRemaining);
// Return any TOKEN_BUY and TOKEN_SELL from the auction to the timelock
_withdrawAnyAvailableTokens({ _excess: false });
emit AuctionStopped({
auctionNumber: _auctionNumber,
tokenBuyReceived: tokenBuyReceived,
tokenSellRemaining: tokenSellRemaining
});
}
// ==============================================================================
// Public Functions
// ==============================================================================
/// @notice Swaps tokenBuys for tokenSells
/// @dev This low-level function should be called from a contract which performs important safety checks
/// @dev Token0 is always the TOKEN_BUY, token1 is always the TOKEN_SELL
/// @dev Maintains uniV2 interface
/// @param amount0Out The amount of tokenBuys to receive
/// @param amount1Out The amount of tokenSells to receive
/// @param to The recipient of the output tokens
/// @param data Callback data
function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes memory data) public nonReentrant {
if (amount0Out != 0) revert ExcessiveTokenBuyOut({ minOut: 0, actualOut: amount0Out });
if (amount1Out == 0) revert InsufficientOutputAmount({ minOut: 1, actualOut: 0 });
// Get the auction info (similar to get reserves in univ2)
uint256 _auctionNumber = details.length - 1;
Detail memory detail = details[_auctionNumber];
// Transfer tokens
IERC20(TOKEN_SELL).safeTransfer(to, amount1Out);
// Callback if necessary for flash swap
if (data.length > 0) {
IUniswapV2Callee(to).uniswapV2Call({
sender: msg.sender,
amount0: amount0Out,
amount1: amount1Out,
data: data
});
}
// Calculate the amount of tokenBuys in
uint256 _tokenBuyBalance = IERC20(TOKEN_BUY).balanceOf(address(this));
uint256 _tokenBuyIn = _tokenBuyBalance - detail.tokenBuyReceived;
// Adheres to uniswap v2 interface, called here to prevent stack-too-deep error
emit Swap({
sender: msg.sender,
amount0In: _tokenBuyIn,
amount1In: 0,
amount0Out: 0,
amount1Out: amount1Out,
to: to
});
// Call the internal function with amountOut
(uint256 _minAmountIn, uint256 _slippagePerTokenSell, uint256 _postPriceSlippage) = _getAmountIn({
_detail: detail,
amountOut: amount1Out
});
// Check invariants
if (_tokenBuyIn < _minAmountIn) revert InsufficientInputAmount({ minIn: _minAmountIn, actualIn: _tokenBuyIn });
if (_minAmountIn == 0) revert InputAmountZero();
// Mutate _auction, which has the previous state
detail.amountLeft -= safeUint128(amount1Out);
detail.tokenBuyReceived = safeUint128(_tokenBuyBalance);
detail.priceLast = safeUint128(_postPriceSlippage);
detail.lastBuyTime = uint32(block.timestamp);
// Write back to state, similar to _update in univ2
details[_auctionNumber] = detail;
// Emit Buy event
emit Buy({
auctionNumber: _auctionNumber,
tokenBuy: TOKEN_BUY,
tokenSell: TOKEN_SELL,
amountIn: safeUint128(_tokenBuyIn),
amountOut: safeUint128(amount1Out),
priceLast: detail.priceLast,
slippagePerTokenSell: safeUint128(_slippagePerTokenSell)
});
}
/// @notice Swaps an exact amount of input tokens for as many output tokens as possible
/// @dev Must have an allowance on the TOKEN_BUY prior to invocation
/// @dev Maintains uniV2 interface
/// @param amountIn The amount of buy tokens to send.
/// @param amountOutMin The minimum amount of sell tokens that must be received for the transaction not to revert
/// @param to Recipient of the output tokens
/// @param deadline Unix timestamp after which the transaction will revert
/// @return _amounts The input token amount and output token amount
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] memory path,
address to,
uint256 deadline
) external returns (uint256[] memory _amounts) {
path; // compile warnings
// Ensure deadline has not passed
if (block.timestamp > deadline) revert Expired();
// Calculate the amount of tokenSells out & check invariant
(uint256 amountOut, , ) = getAmountOut({ amountIn: amountIn, _revertOnOverAmountLeft: true });
if (amountOut < amountOutMin) {
revert InsufficientOutputAmount({ minOut: amountOutMin, actualOut: amountOut });
}
// Interactions: Transfer tokenBuys to the contract
IERC20(TOKEN_BUY).safeTransferFrom(msg.sender, address(this), amountIn);
// Call the swap function
swap({ amount0Out: 0, amount1Out: amountOut, to: to, data: new bytes(0) });
// Set return values
_amounts = new uint256[](2);
_amounts[0] = amountIn;
_amounts[1] = amountOut;
}
/// @notice Receives an exact amount of output tokens for as few input tokens as possible
/// @dev Must have an allowance on the TOKEN_BUY prior to invocation
/// @dev Maintains uniV2 interface
/// @param amountOut The amount of sell tokens to receive
/// @param amountInMax The maximum amount of buy tokens that can be required before the transaction reverts
/// @param to Recipient of the output tokens
/// @param deadline Unix timestamp after which the transaction will revert
/// @return _amounts The input token amount and output token amount
function swapTokensForExactTokens(
uint256 amountOut,
uint256 amountInMax,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory _amounts) {
path; // compile warning
// Ensure deadline has not passed
if (block.timestamp > deadline) revert Expired();
// Calculate the amount of tokenBuys in & check invariant
(uint256 amountIn, , ) = getAmountIn({ amountOut: amountOut });
if (amountIn > amountInMax) revert ExcessiveInputAmount({ minIn: amountInMax, actualIn: amountIn });
// Interactions: Transfer tokenBuys to the contract
IERC20(TOKEN_BUY).safeTransferFrom(msg.sender, address(this), amountIn);
// Call the swap function
swap({ amount0Out: 0, amount1Out: amountOut, to: to, data: new bytes(0) });
// Set return variable
_amounts = new uint256[](2);
_amounts[0] = amountIn;
_amounts[1] = amountOut;
}
// ==============================================================================
// Helpers
// ==============================================================================
/// @notice Withdraw available TOKEN_BUY and TOKEN_SELL on startAuction() and stopAuction()
/// @param _excess Whether to bookkeep any excess tokens received outside of auction
function _withdrawAnyAvailableTokens(bool _excess) private {
_withdrawIfTokenBalance({ _token: TOKEN_BUY, _priorBalance: 0, _excess: _excess });
_withdrawIfTokenBalance({ _token: TOKEN_SELL, _priorBalance: 0, _excess: _excess });
}
/// @notice Withdraw available TOKEN_BUY and TOKEN_SELL on startAuction() and stopAuction()
/// @param _token Address of the token you want to withdraw
/// @param _priorBalance Prior balance of the _token
/// @param _excess Whether to bookkeep any excess tokens received outside of auction
function _withdrawIfTokenBalance(address _token, uint256 _priorBalance, bool _excess) private {
// Fetch the current balance of _token
uint256 balance = IERC20(_token).balanceOf(address(this));
// If the current balance is higher than the prior balance
if (balance > _priorBalance) {
uint256 amount = balance - _priorBalance;
// Bookkeep any excess token received
if (_excess) {
Detail storage detail = details[details.length - 1];
if (_token == TOKEN_BUY) {
detail.amountExcessBuy += safeUint128(amount);
} else {
// token == TOKEN_SELL
detail.amountExcessSell += safeUint128(amount);
}
}
IERC20(_token).safeTransfer(msg.sender, amount);
}
}
/// @dev Overflow protection
function safeUint128(uint256 number) internal pure returns (uint128 casted) {
if (number > type(uint128).max) revert Overflow();
casted = uint128(number);
}
// ==============================================================================
// Errors
// ==============================================================================
/// @notice Emitted when a user attempts to start an auction selling too few tokens
error AmountListedTooLow();
/// @notice Emitted when a user attempts to end an auction that has been stopped
error AuctionNotActive();
/// @notice Emitted when a user attempts to interact with an auction that has expired
error AuctionExpired();
/// @notice Emitted when a user attempts to start a new auction before the previous one has been stopped (via ```stopAuction()```)
error LastAuctionStillActive();
/// @notice Emitted when a user attempts to swap a given amount of buy tokens that would result in an insufficient amount of sell tokens
/// @param minOut Minimum out that the user expects
/// @param actualOut Actual amount out that would occur
error InsufficientOutputAmount(uint256 minOut, uint256 actualOut);
/// @notice Emitted when a user attempts to swap an insufficient amount of buy tokens
/// @param minIn Minimum in that the contract requires
/// @param actualIn Actual amount in that has been deposited
error InsufficientInputAmount(uint256 minIn, uint256 actualIn);
/// @notice Emitted when a user attempts to swap an excessive amount of buy tokens for aa given amount of sell tokens
/// @param minIn Minimum in that the user expects
/// @param actualIn Actual amount in that would occur
error ExcessiveInputAmount(uint256 minIn, uint256 actualIn);
/// @notice Emitted when a user attempts to buy more sell tokens than are left in the auction
error InsufficientTokenSellsAvailable();
/// @notice Emitted when attempting to swap where the calculated amountIn is 0
error InputAmountZero();
/// @notice Emitted when a user attempts to buy the tokenBuy using the swap() function
error ExcessiveTokenBuyOut(uint256 minOut, uint256 actualOut);
/// @notice Emitted when a user attempts to make a swap after the transaction deadline has passed
error Expired();
/// @notice Emitted when a user attempts to use an invalid buy token
error InvalidTokenIn();
/// @notice Emitted when a user attempts to use an invalid sell token
error InvalidTokenOut();
/// @notice Emitted when calling `startAuction()` when `StartAuctionParams.priceMin == 0 && StartAuctionParams.priceSlippage == 0`
error PriceMinAndSlippageBothZero();
/// @notice Emitted when attempting to call a uni-v2 pair function that is not supported by this contract
error NotImplemented();
/// @notice Emitted when downcasting a uint on type overflow
error Overflow();
/// @notice Emitted when a user attempts to start an auction with `_params.priceStart < _params.priceMin`
error PriceStartLessThanPriceMin();
// ==============================================================================
// Events
// ==============================================================================
/// @dev Emitted when an auction is stopped
/// @param auctionNumber The ID of the auction
/// @param tokenBuyReceived Amount of tokenBuy obtained from the auction
/// @param tokenSellRemaining Amount of unsold tokenSells left over
event AuctionStopped(uint256 auctionNumber, uint256 tokenBuyReceived, uint256 tokenSellRemaining);
/// @dev Emitted when a swap occurs and has more information than the ```Swap``` event
/// @param auctionNumber The ID of the auction, and index in the details array
/// @param tokenBuy The token used to buy the tokenSell being auctioned off
/// @param tokenSell The token being auctioned off
/// @param amountIn Amount of tokenBuy in
/// @param amountOut Amount of tokenSell out
/// @param priceLast The execution price of the buy
/// @param slippagePerTokenSell How many tokenBuys (per tokenSell) were added as slippage
event Buy(
uint256 auctionNumber,
address tokenBuy,
address tokenSell,
uint128 amountIn,
uint128 amountOut,
uint128 priceLast,
uint128 slippagePerTokenSell
);
/// @notice Emitted when a swap occurs
/// @param sender The address of the sender
/// @param amount0In The amount of TOKEN_BUY in
/// @param amount1In The amount of TOKEN_SELL in
/// @param amount0Out The amount of TOKEN_BUY out
/// @param amount1Out The amount of TOKEN_SELL out
/// @param to The address of the recipient
event Swap(
address indexed sender,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out,
address indexed to
);
/// @dev Emitted when an auction is started
/// @param auctionNumber The ID of the auction
/// @param amountListed Amount of tokenSell being sold
/// @param priceStart Starting price of the tokenSell, in tokenBuy
/// @param priceMin Minimum price of the tokenSell, in tokenBuy
/// @param priceDecay Price decay, per day, using PRECISION
/// @param priceSlippage Slippage fraction. E.g (0.01 * PRECISION) = 1%
/// @param expiry Expiration time of the auction
event AuctionStarted(
uint256 auctionNumber,
uint128 amountListed,
uint128 priceStart,
uint128 priceMin,
uint128 priceDecay,
uint128 priceSlippage,
uint32 expiry
);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*/
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
mapping(address account => mapping(address spender => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `value`.
*/
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `value`.
* - the caller must have allowance for ``from``'s tokens of at least
* `value`.
*/
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
/**
* @dev Moves a `value` amount of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
/**
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
* this function.
*
* Emits a {Transfer} event.
*/
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
// Overflow not possible: value <= fromBalance <= totalSupply.
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
_totalSupply -= value;
}
} else {
unchecked {
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
_balances[to] += value;
}
}
emit Transfer(from, to, value);
}
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
* Relies on the `_update` mechanism
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
* Relies on the `_update` mechanism.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead
*/
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
/**
* @dev Sets `value` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
* `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
* `Approval` event during `transferFrom` operations.
*
* Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
* true using the following override:
* ```
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
* super._approve(owner, spender, value, true);
* }
* ```
*
* Requirements are the same as {_approve}.
*/
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
_allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `value`.
*
* Does not update the allowance value in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Does not emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC20Permit} from "../extensions/IERC20Permit.sol";
import {Address} from "../../../utils/Address.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
using Address for address;
/**
* @dev An operation with an ERC20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value)));
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0)));
_callOptionalReturn(token, approvalCall);
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*/
function _callOptionalReturn(IERC20 token, bytes memory data) private {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
// the target address contains contract code and also asserts for success in the low-level call.
bytes memory returndata = address(token).functionCall(data);
if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
* on the return value: the return value is optional (but if data is returned, it must not be false).
* @param token The token targeted by the call.
* @param data The call data (encoded using abi.encode or one of its variants).
*
* This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
*/
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
// We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
// we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
// and not revert is the subcall reverts.
(bool success, bytes memory returndata) = address(token).call(data);
return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0;
}
}// SPDX-License-Identifier: ISC
pragma solidity >=0.8.0;
// ====================================================================
// | ______ _______ |
// | / _____________ __ __ / ____(_____ ____ _____ ________ |
// | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ |
// | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ |
// | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ |
// | |
// ====================================================================
// ========================== Timelock2Step ===========================
// ====================================================================
// Frax Finance: https://github.com/FraxFinance
// Primary Author
// Drake Evans: https://github.com/DrakeEvans
// Reviewers
// Dennis: https://github.com/denett
// ====================================================================
/// @title Timelock2Step
/// @author Drake Evans (Frax Finance) https://github.com/drakeevans
/// @dev Inspired by OpenZeppelin's Ownable2Step contract
/// @notice An abstract contract which contains 2-step transfer and renounce logic for a timelock address
abstract contract Timelock2Step {
/// @notice The pending timelock address
address public pendingTimelockAddress;
/// @notice The current timelock address
address public timelockAddress;
constructor(address _timelockAddress) {
timelockAddress = _timelockAddress;
}
// ============================================================================================
// Functions: External Functions
// ============================================================================================
/// @notice The ```transferTimelock``` function initiates the timelock transfer
/// @dev Must be called by the current timelock
/// @param _newTimelock The address of the nominated (pending) timelock
function transferTimelock(address _newTimelock) external virtual {
_requireSenderIsTimelock();
_transferTimelock(_newTimelock);
}
/// @notice The ```acceptTransferTimelock``` function completes the timelock transfer
/// @dev Must be called by the pending timelock
function acceptTransferTimelock() external virtual {
_requireSenderIsPendingTimelock();
_acceptTransferTimelock();
}
/// @notice The ```renounceTimelock``` function renounces the timelock after setting pending timelock to current timelock
/// @dev Pending timelock must be set to current timelock before renouncing, creating a 2-step renounce process
function renounceTimelock() external virtual {
_requireSenderIsTimelock();
_requireSenderIsPendingTimelock();
_transferTimelock(address(0));
_setTimelock(address(0));
}
// ============================================================================================
// Functions: Internal Actions
// ============================================================================================
/// @notice The ```_transferTimelock``` function initiates the timelock transfer
/// @dev This function is to be implemented by a public function
/// @param _newTimelock The address of the nominated (pending) timelock
function _transferTimelock(address _newTimelock) internal {
pendingTimelockAddress = _newTimelock;
emit TimelockTransferStarted(timelockAddress, _newTimelock);
}
/// @notice The ```_acceptTransferTimelock``` function completes the timelock transfer
/// @dev This function is to be implemented by a public function
function _acceptTransferTimelock() internal {
pendingTimelockAddress = address(0);
_setTimelock(msg.sender);
}
/// @notice The ```_setTimelock``` function sets the timelock address
/// @dev This function is to be implemented by a public function
/// @param _newTimelock The address of the new timelock
function _setTimelock(address _newTimelock) internal {
emit TimelockTransferred(timelockAddress, _newTimelock);
timelockAddress = _newTimelock;
}
// ============================================================================================
// Functions: Internal Checks
// ============================================================================================
/// @notice The ```_isTimelock``` function checks if _address is current timelock address
/// @param _address The address to check against the timelock
/// @return Whether or not msg.sender is current timelock address
function _isTimelock(address _address) internal view returns (bool) {
return _address == timelockAddress;
}
/// @notice The ```_requireIsTimelock``` function reverts if _address is not current timelock address
/// @param _address The address to check against the timelock
function _requireIsTimelock(address _address) internal view {
if (!_isTimelock(_address)) revert AddressIsNotTimelock(timelockAddress, _address);
}
/// @notice The ```_requireSenderIsTimelock``` function reverts if msg.sender is not current timelock address
/// @dev This function is to be implemented by a public function
function _requireSenderIsTimelock() internal view {
_requireIsTimelock(msg.sender);
}
/// @notice The ```_isPendingTimelock``` function checks if the _address is pending timelock address
/// @dev This function is to be implemented by a public function
/// @param _address The address to check against the pending timelock
/// @return Whether or not _address is pending timelock address
function _isPendingTimelock(address _address) internal view returns (bool) {
return _address == pendingTimelockAddress;
}
/// @notice The ```_requireIsPendingTimelock``` function reverts if the _address is not pending timelock address
/// @dev This function is to be implemented by a public function
/// @param _address The address to check against the pending timelock
function _requireIsPendingTimelock(address _address) internal view {
if (!_isPendingTimelock(_address)) revert AddressIsNotPendingTimelock(pendingTimelockAddress, _address);
}
/// @notice The ```_requirePendingTimelock``` function reverts if msg.sender is not pending timelock address
/// @dev This function is to be implemented by a public function
function _requireSenderIsPendingTimelock() internal view {
_requireIsPendingTimelock(msg.sender);
}
// ============================================================================================
// Functions: Events
// ============================================================================================
/// @notice The ```TimelockTransferStarted``` event is emitted when the timelock transfer is initiated
/// @param previousTimelock The address of the previous timelock
/// @param newTimelock The address of the new timelock
event TimelockTransferStarted(address indexed previousTimelock, address indexed newTimelock);
/// @notice The ```TimelockTransferred``` event is emitted when the timelock transfer is completed
/// @param previousTimelock The address of the previous timelock
/// @param newTimelock The address of the new timelock
event TimelockTransferred(address indexed previousTimelock, address indexed newTimelock);
// ============================================================================================
// Functions: Errors
// ============================================================================================
/// @notice Emitted when timelock is transferred
error AddressIsNotTimelock(address timelockAddress, address actualAddress);
/// @notice Emitted when pending timelock is transferred
error AddressIsNotPendingTimelock(address pendingTimelockAddress, address actualAddress);
}// SPDX-License-Identifier: ISC
pragma solidity ^0.8.23;
interface IUniswapV2Callee {
function uniswapV2Call(address sender, uint256 amount0, uint256 amount1, bytes calldata data) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)
pragma solidity ^0.8.20;
/**
* @dev Standard ERC20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
* https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
*
* Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
* presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
* need to send a transaction, and thus is not required to hold Ether at all.
*
* ==== Security Considerations
*
* There are two important considerations concerning the use of `permit`. The first is that a valid permit signature
* expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be
* considered as an intention to spend the allowance in any specific way. The second is that because permits have
* built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should
* take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be
* generally recommended is:
*
* ```solidity
* function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {
* try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}
* doThing(..., value);
* }
*
* function doThing(..., uint256 value) public {
* token.safeTransferFrom(msg.sender, address(this), value);
* ...
* }
* ```
*
* Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of
* `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also
* {SafeERC20-safeTransferFrom}).
*
* Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so
* contracts should have entry points that don't rely on permit.
*/
interface IERC20Permit {
/**
* @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
* given ``owner``'s signed approval.
*
* IMPORTANT: The same issues {IERC20-approve} has related to transaction
* ordering also apply here.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `deadline` must be a timestamp in the future.
* - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
* over the EIP712-formatted function arguments.
* - the signature must use ``owner``'s current nonce (see {nonces}).
*
* For more information on the signature format, see the
* https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
* section].
*
* CAUTION: See Security Considerations above.
*/
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
/**
* @dev Returns the current nonce for `owner`. This value must be
* included whenever a signature is generated for {permit}.
*
* Every successful call to {permit} increases ``owner``'s nonce by one. This
* prevents a signature from being used multiple times.
*/
function nonces(address owner) external view returns (uint256);
/**
* @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
*/
// solhint-disable-next-line func-name-mixedcase
function DOMAIN_SEPARATOR() external view returns (bytes32);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)
pragma solidity ^0.8.20;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @dev The ETH balance of the account is not enough to perform the operation.
*/
error AddressInsufficientBalance(address account);
/**
* @dev There's no code at `target` (it is not a contract).
*/
error AddressEmptyCode(address target);
/**
* @dev A call to an address target failed. The target may have reverted.
*/
error FailedInnerCall();
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
if (address(this).balance < amount) {
revert AddressInsufficientBalance(address(this));
}
(bool success, ) = recipient.call{value: amount}("");
if (!success) {
revert FailedInnerCall();
}
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason or custom error, it is bubbled
* up by this function (like regular Solidity function calls). However, if
* the call reverted with no returned reason, this function reverts with a
* {FailedInnerCall} error.
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*/
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
if (address(this).balance < value) {
revert AddressInsufficientBalance(address(this));
}
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
* was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
* unsuccessful call.
*/
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata
) internal view returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
// only check if target is a contract if the call was successful and the return data is empty
// otherwise we already know that it was a contract
if (returndata.length == 0 && target.code.length == 0) {
revert AddressEmptyCode(target);
}
return returndata;
}
}
/**
* @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
* revert reason or with a default {FailedInnerCall} error.
*/
function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
if (!success) {
_revert(returndata);
} else {
return returndata;
}
}
/**
* @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
*/
function _revert(bytes memory returndata) private pure {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
/// @solidity memory-safe-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert FailedInnerCall();
}
}
}{
"remappings": [
"forge-std/=node_modules/forge-std/src/",
"solidity-bytes-utils/=node_modules/solidity-bytes-utils/",
"@openzeppelin/=node_modules/@openzeppelin/",
"@chainlink/=node_modules/@chainlink/",
"ds-test/=node_modules/ds-test/src/",
"frax-std/=node_modules/frax-std/src/",
"frax-standard-solidity/=node_modules/frax-standard-solidity/"
],
"optimizer": {
"enabled": true,
"runs": 100000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": false,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_timelock","type":"address"},{"internalType":"address","name":"_tokenBuy","type":"address"},{"internalType":"address","name":"_tokenSell","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"pendingTimelockAddress","type":"address"},{"internalType":"address","name":"actualAddress","type":"address"}],"name":"AddressIsNotPendingTimelock","type":"error"},{"inputs":[{"internalType":"address","name":"timelockAddress","type":"address"},{"internalType":"address","name":"actualAddress","type":"address"}],"name":"AddressIsNotTimelock","type":"error"},{"inputs":[],"name":"AmountListedTooLow","type":"error"},{"inputs":[],"name":"AuctionExpired","type":"error"},{"inputs":[],"name":"AuctionNotActive","type":"error"},{"inputs":[{"internalType":"uint256","name":"minIn","type":"uint256"},{"internalType":"uint256","name":"actualIn","type":"uint256"}],"name":"ExcessiveInputAmount","type":"error"},{"inputs":[{"internalType":"uint256","name":"minOut","type":"uint256"},{"internalType":"uint256","name":"actualOut","type":"uint256"}],"name":"ExcessiveTokenBuyOut","type":"error"},{"inputs":[],"name":"Expired","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InputAmountZero","type":"error"},{"inputs":[{"internalType":"uint256","name":"minIn","type":"uint256"},{"internalType":"uint256","name":"actualIn","type":"uint256"}],"name":"InsufficientInputAmount","type":"error"},{"inputs":[{"internalType":"uint256","name":"minOut","type":"uint256"},{"internalType":"uint256","name":"actualOut","type":"uint256"}],"name":"InsufficientOutputAmount","type":"error"},{"inputs":[],"name":"InsufficientTokenSellsAvailable","type":"error"},{"inputs":[],"name":"InvalidTokenIn","type":"error"},{"inputs":[],"name":"InvalidTokenOut","type":"error"},{"inputs":[],"name":"LastAuctionStillActive","type":"error"},{"inputs":[],"name":"NotImplemented","type":"error"},{"inputs":[],"name":"Overflow","type":"error"},{"inputs":[],"name":"PriceMinAndSlippageBothZero","type":"error"},{"inputs":[],"name":"PriceStartLessThanPriceMin","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"auctionNumber","type":"uint256"},{"indexed":false,"internalType":"uint128","name":"amountListed","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"priceStart","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"priceMin","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"priceDecay","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"priceSlippage","type":"uint128"},{"indexed":false,"internalType":"uint32","name":"expiry","type":"uint32"}],"name":"AuctionStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"auctionNumber","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenBuyReceived","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenSellRemaining","type":"uint256"}],"name":"AuctionStopped","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"auctionNumber","type":"uint256"},{"indexed":false,"internalType":"address","name":"tokenBuy","type":"address"},{"indexed":false,"internalType":"address","name":"tokenSell","type":"address"},{"indexed":false,"internalType":"uint128","name":"amountIn","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"amountOut","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"priceLast","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"slippagePerTokenSell","type":"uint128"}],"name":"Buy","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1Out","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousTimelock","type":"address"},{"indexed":true,"internalType":"address","name":"newTimelock","type":"address"}],"name":"TimelockTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousTimelock","type":"address"},{"indexed":true,"internalType":"address","name":"newTimelock","type":"address"}],"name":"TimelockTransferred","type":"event"},{"inputs":[],"name":"MINIMUM_LIQUIDITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_BUY","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TOKEN_SELL","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptTransferTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"details","outputs":[{"internalType":"uint128","name":"amountListed","type":"uint128"},{"internalType":"uint128","name":"amountLeft","type":"uint128"},{"internalType":"uint128","name":"amountExcessBuy","type":"uint128"},{"internalType":"uint128","name":"amountExcessSell","type":"uint128"},{"internalType":"uint128","name":"tokenBuyReceived","type":"uint128"},{"internalType":"uint128","name":"priceLast","type":"uint128"},{"internalType":"uint128","name":"priceMin","type":"uint128"},{"internalType":"uint64","name":"priceDecay","type":"uint64"},{"internalType":"uint64","name":"priceSlippage","type":"uint64"},{"internalType":"uint32","name":"lastBuyTime","type":"uint32"},{"internalType":"uint32","name":"expiry","type":"uint32"},{"internalType":"bool","name":"active","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"detailsLength","outputs":[{"internalType":"uint256","name":"_length","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"_slippagePerTokenSell","type":"uint256"},{"internalType":"uint256","name":"_postPriceSlippage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAmountInMax","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"_slippagePerTokenSell","type":"uint256"},{"internalType":"uint256","name":"_postPriceSlippage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"bool","name":"_revertOnOverAmountLeft","type":"bool"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"_slippagePerTokenSell","type":"uint256"},{"internalType":"uint256","name":"_postPriceSlippage","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_auctionNumber","type":"uint256"}],"name":"getDetailStruct","outputs":[{"components":[{"internalType":"uint128","name":"amountListed","type":"uint128"},{"internalType":"uint128","name":"amountLeft","type":"uint128"},{"internalType":"uint128","name":"amountExcessBuy","type":"uint128"},{"internalType":"uint128","name":"amountExcessSell","type":"uint128"},{"internalType":"uint128","name":"tokenBuyReceived","type":"uint128"},{"internalType":"uint128","name":"priceLast","type":"uint128"},{"internalType":"uint128","name":"priceMin","type":"uint128"},{"internalType":"uint64","name":"priceDecay","type":"uint64"},{"internalType":"uint64","name":"priceSlippage","type":"uint64"},{"internalType":"uint32","name":"lastBuyTime","type":"uint32"},{"internalType":"uint32","name":"expiry","type":"uint32"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct SlippageAuction.Detail","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLatestAuction","outputs":[{"components":[{"internalType":"uint128","name":"amountListed","type":"uint128"},{"internalType":"uint128","name":"amountLeft","type":"uint128"},{"internalType":"uint128","name":"amountExcessBuy","type":"uint128"},{"internalType":"uint128","name":"amountExcessSell","type":"uint128"},{"internalType":"uint128","name":"tokenBuyReceived","type":"uint128"},{"internalType":"uint128","name":"priceLast","type":"uint128"},{"internalType":"uint128","name":"priceMin","type":"uint128"},{"internalType":"uint64","name":"priceDecay","type":"uint64"},{"internalType":"uint64","name":"priceSlippage","type":"uint64"},{"internalType":"uint32","name":"lastBuyTime","type":"uint32"},{"internalType":"uint32","name":"expiry","type":"uint32"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct SlippageAuction.Detail","name":"_latestAuction","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPreSlippagePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"amountListed","type":"uint128"},{"internalType":"uint128","name":"amountLeft","type":"uint128"},{"internalType":"uint128","name":"amountExcessBuy","type":"uint128"},{"internalType":"uint128","name":"amountExcessSell","type":"uint128"},{"internalType":"uint128","name":"tokenBuyReceived","type":"uint128"},{"internalType":"uint128","name":"priceLast","type":"uint128"},{"internalType":"uint128","name":"priceMin","type":"uint128"},{"internalType":"uint64","name":"priceDecay","type":"uint64"},{"internalType":"uint64","name":"priceSlippage","type":"uint64"},{"internalType":"uint32","name":"lastBuyTime","type":"uint32"},{"internalType":"uint32","name":"expiry","type":"uint32"},{"internalType":"bool","name":"active","type":"bool"}],"internalType":"struct SlippageAuction.Detail","name":"_detail","type":"tuple"}],"name":"getPreSlippagePrice","outputs":[{"internalType":"uint256","name":"_price","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint112","name":"","type":"uint112"},{"internalType":"uint112","name":"","type":"uint112"},{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"kLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingTimelockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price0CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"price1CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"renounceTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"skim","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"internalType":"uint128","name":"amountListed","type":"uint128"},{"internalType":"uint128","name":"priceStart","type":"uint128"},{"internalType":"uint128","name":"priceMin","type":"uint128"},{"internalType":"uint64","name":"priceDecay","type":"uint64"},{"internalType":"uint64","name":"priceSlippage","type":"uint64"},{"internalType":"uint32","name":"expiry","type":"uint32"}],"internalType":"struct SlippageAuction.StartAuctionParams","name":"_params","type":"tuple"}],"name":"startAuction","outputs":[{"internalType":"uint256","name":"_auctionNumber","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopAuction","outputs":[{"internalType":"uint256","name":"tokenBuyReceived","type":"uint256"},{"internalType":"uint256","name":"tokenSellRemaining","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0Out","type":"uint256"},{"internalType":"uint256","name":"amount1Out","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"timelockAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newTimelock","type":"address"}],"name":"transferTimelock","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"version","outputs":[{"internalType":"uint256","name":"_major","type":"uint256"},{"internalType":"uint256","name":"_minor","type":"uint256"},{"internalType":"uint256","name":"_patch","type":"uint256"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
6101006040523480156200001257600080fd5b506040516200416338038062004163833981016040819052620000359162000136565b60016000908155600280546001600160a01b0319166001600160a01b0386811691909117909155604080516395d89b4160e01b81529051918416926395d89b41926004808401938290030181865afa15801562000096573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620000c09190810190620001bc565b604051602001620000d2919062000274565b60405160208183030381529060405260039081620000f1919062000340565b506001600160a01b039182166080819052911660a081905260c09190915260e052506200040c565b80516001600160a01b03811681146200013157600080fd5b919050565b6000806000606084860312156200014c57600080fd5b620001578462000119565b9250620001676020850162000119565b9150620001776040850162000119565b90509250925092565b634e487b7160e01b600052604160045260246000fd5b60005b83811015620001b357818101518382015260200162000199565b50506000910152565b600060208284031215620001cf57600080fd5b81516001600160401b0380821115620001e757600080fd5b818401915084601f830112620001fc57600080fd5b81518181111562000211576200021162000180565b604051601f8201601f19908116603f011681019083821181831017156200023c576200023c62000180565b816040528281528760208487010111156200025657600080fd5b6200026983602083016020880162000196565b979650505050505050565b70029b634b83830b3b2a0bab1ba34b7b71d1607d1b815260008251620002a281601185016020870162000196565b9190910160110192915050565b600181811c90821680620002c457607f821691505b602082108103620002e557634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200033b576000816000526020600020601f850160051c81016020861015620003165750805b601f850160051c820191505b81811015620003375782815560010162000322565b5050505b505050565b81516001600160401b038111156200035c576200035c62000180565b62000374816200036d8454620002af565b84620002eb565b602080601f831160018114620003ac5760008415620003935750858301515b600019600386901b1c1916600185901b17855562000337565b600085815260208120601f198616915b82811015620003dd57888601518255948401946001909101908401620003bc565b5085821015620003fc5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60805160a05160c05160e051613cad620004b6600039600061061e015260006103870152600081816104e30152818161085101528181610d52015281816111b4015281816114a9015281816115d5015281816126d10152612daa0152600081816104720152818161093f01528181610d310152818161146801528181611524015281816117e901528181611cda015281816127ee01528181612c1a0152612d7e0152613cad6000f3fe608060405234801561001057600080fd5b50600436106102ad5760003560e01c80635909c0d51161017b578063aaf5eb68116100d8578063d21220a71161008c578063f140a35a11610071578063f140a35a14610653578063f6ccaad414610666578063fff6cae9146102c557600080fd5b8063d21220a714610619578063e40dc7031461064057600080fd5b8063ba9a7a56116100bd578063ba9a7a56146104d6578063bc25cf7714610600578063c45a01551461061157600080fd5b8063aaf5eb68146105de578063afa29031146105ed57600080fd5b80637464fc3d1161012f5780638803dbee116101145780638803dbee146105155780639b4faa8014610528578063a005ec7a1461053b57600080fd5b80637464fc3d146104d657806385f8c259146102c757600080fd5b80635c80aeee116101605780635c80aeee146104de5780635f28bc5b146105055780636df00be81461050d57600080fd5b80635909c0d5146104d65780635a3d5493146104d657600080fd5b8063269b9a08116102295780634bc66f32116101dd57806354fd4d50116101c257806354fd4d50146104bc57806355d256e9146104c6578063561ad39f146104ce57600080fd5b80634bc66f32146104945780634f8b4ae7146104b457600080fd5b8063450140951161020e5780634501409514610447578063485cc9551461045a5780634b4349d51461046d57600080fd5b8063269b9a081461040a57806338ed17391461042757600080fd5b8063090f3f501161028057806311106ee21161026557806311106ee2146103a95780631125f13f146103d7578063241a277f146103ea57600080fd5b8063090f3f501461033d5780630dfe16811461038257600080fd5b8063022c0d9f146102b2578063054d50d4146102c757806306fdde03146102ed5780630902f1ac14610302575b600080fd5b6102c56102c0366004613355565b61066e565b005b6102da6102d536600461342c565b610e0e565b6040519081526020015b60405180910390f35b6102f5610e42565b6040516102e491906134c6565b61030a610ed0565b604080516dffffffffffffffffffffffffffff948516815293909216602084015263ffffffff16908201526060016102e4565b60015461035d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102e4565b61035d7f000000000000000000000000000000000000000000000000000000000000000081565b6103bc6103b73660046134f2565b610f07565b604080519384526020840192909252908201526060016102e4565b6102da6103e5366004613522565b6111b0565b6103fd6103f836600461354e565b61124a565b6040516102e49190613567565b6104126113c9565b604080519283526020830191909152016102e4565b61043a6104353660046136c3565b61173e565b6040516102e4919061379e565b6102c56104553660046137e2565b6118b4565b6102c56104683660046137fd565b6118c5565b61035d7f000000000000000000000000000000000000000000000000000000000000000081565b60025461035d9073ffffffffffffffffffffffffffffffffffffffff1681565b6102c56118f7565b60016000816103bc565b6102da61191d565b6004546102da565b6102da610e0e565b61035d7f000000000000000000000000000000000000000000000000000000000000000081565b6103fd611a53565b6103bc611ae4565b61043a610523366004613827565b611c31565b6103bc61053636600461354e565b611d7a565b61054e61054936600461354e565b611ec9565b604080516fffffffffffffffffffffffffffffffff9d8e1681529b8d1660208d0152998c16998b0199909952968a1660608a0152948916608089015292881660a0880152961660c086015267ffffffffffffffff95861660e08601529490941661010084015263ffffffff93841661012084015292909216610140820152901515610160820152610180016102e4565b6102da670de0b6b3a764000081565b6102da6105fb3660046138c9565b611f9d565b6102c561060e3660046137e2565b50565b61035d610e0e565b61035d7f000000000000000000000000000000000000000000000000000000000000000081565b6102da61064e366004613927565b61271a565b6102da610661366004613522565b6127ea565b6102c561287c565b61067661288c565b83156106bd576040517f0ed4217800000000000000000000000000000000000000000000000000000000815260006004820152602481018590526044015b60405180910390fd5b82600003610701576040517fd28d3eb500000000000000000000000000000000000000000000000000000000815260016004820152600060248201526044016106b4565b60045460009061071390600190613a42565b905060006004828154811061072a5761072a613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff8082166101208401526401000000008204811661014084015260ff6801000000000000000090920491909116151561016083015290915061087c9073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690869088906128cf16565b82511561090e576040517f10d1e85c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516906310d1e85c906108db9033908a908a908990600401613a84565b600060405180830381600087803b1580156108f557600080fd5b505af1158015610909573d6000803e3d6000fd5b505050505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561099b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109bf9190613ac9565b9050600082608001516fffffffffffffffffffffffffffffffff16826109e59190613a42565b6040805182815260006020820181905281830152606081018a9052905191925073ffffffffffffffffffffffffffffffffffffffff88169133917fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822919081900360800190a36000806000610a59868b612955565b92509250925082841015610aa3576040517fec3e79fb00000000000000000000000000000000000000000000000000000000815260048101849052602481018590526044016106b4565b82600003610add576040517f55eaa09500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ae68a612adc565b86602001818151610af79190613ae2565b6fffffffffffffffffffffffffffffffff16905250610b1585612adc565b6fffffffffffffffffffffffffffffffff166080870152610b3581612adc565b6fffffffffffffffffffffffffffffffff1660a087015263ffffffff42166101208701526004805487919089908110610b7057610b70613a55565b60009182526020918290208351928401516fffffffffffffffffffffffffffffffff9081167001000000000000000000000000000000009081029482169490941760059093029091019182556040840151606085015182168402908216176001830155608084015160a08501518216840290821617600283015560c084015160038301805460e087015161010088015167ffffffffffffffff90811678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff919092169097027fffffffffffffffff00000000000000000000000000000000000000000000000090921693909416929092179190911793909316179091556101208201516004909101805461014084015161016090940151151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff63ffffffff958616640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909316959094169490941717919091169190911790557f4c8e97934cb2d5c0876fe70b82782d28160e62ef5844aa6ba80e10174feed687877f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000610d7a88612adc565b610d838f612adc565b8b60a00151610d9189612adc565b6040805197885273ffffffffffffffffffffffffffffffffffffffff968716602089015294909516868501526fffffffffffffffffffffffffffffffff92831660608701529082166080860152811660a085015290911660c0830152519081900360e00190a150505050505050610e086001600055565b50505050565b60006040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60038054610e4f90613b12565b80601f0160208091040260200160405190810160405280929190818152602001828054610e7b90613b12565b8015610ec85780601f10610e9d57610100808354040283529160200191610ec8565b820191906000526020600020905b815481529060010190602001808311610eab57829003601f168201915b505050505081565b60008060006040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000806001600480549050610f1f9190613a42565b9050600060048281548110610f3657610f36613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff80821661012084015264010000000082041661014083015260ff680100000000000000009091041615156101608201819052909150611076576040517f69b8d0fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610140015163ffffffff1642106110ba576040517f04a5e67c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006110c58261271a565b9050670de0b6b3a76400008883610100015167ffffffffffffffff166110eb9190613b5f565b6110f59190613b76565b94506111018582613bb1565b611113670de0b6b3a76400008a613b5f565b61111d9190613b76565b955081602001516fffffffffffffffffffffffffffffffff1686111561118f578615611175576040517ffc43992200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81602001516fffffffffffffffffffffffffffffffff1695505b61119a856002613b5f565b6111a49082613bb1565b93505050509250925092565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614611237576040517f1b6d1fa000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61124083611d7a565b5090949350505050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810191909152600482815481106112be576112be613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff80821661012084015264010000000082041661014083015260ff6801000000000000000090910416151561016082015292915050565b6000806113d461288c565b6113dc612b2c565b6004546000906113ee90600190613a42565b905060006004828154811061140557611405613a55565b906000526020600020906005020190508060040160089054906101000a900460ff1661145d576040517f69b8d0fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028101546114a1907f0000000000000000000000000000000000000000000000000000000000000000906fffffffffffffffffffffffffffffffff166001612b35565b80546114f6907f00000000000000000000000000000000000000000000000000000000000000009070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166001612b35565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613ac9565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529094507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611631573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116559190613ac9565b6004820180547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1690556002820180546fffffffffffffffffffffffffffffffff8088167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117909155825481831670010000000000000000000000000000000002911617825592506116ed6000612d79565b60408051838152602081018690529081018490527fdeb58d7180330f713ed3023619d340a8f4f264aee7cd0707f8997ce863182e999060600160405180910390a1505061173a6001600055565b9091565b60608142111561177a576040517f203d82d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611787876001610f07565b50509050858110156117cf576040517fd28d3eb500000000000000000000000000000000000000000000000000000000815260048101879052602481018290526044016106b4565b61181173ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001633308a612dd1565b61184a60008286825b6040519080825280601f01601f191660200182016040528015611844576020820181803683370190505b5061066e565b6040805160028082526060820183529091602083019080368337019050509150868260008151811061187e5761187e613a55565b602002602001018181525050808260018151811061189e5761189e613a55565b6020026020010181815250505095945050505050565b6118bc612b2c565b61060e81612e17565b6040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118ff612b2c565b611907612e8e565b6119116000612e17565b61191b6000612e97565b565b60048054600091611a4e9161193490600190613a42565b8154811061194457611944613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff80821661012084015264010000000082041661014083015260ff6801000000000000000090910416151561016082015261271a565b905090565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290526101608101919091526004546000819003611ac4575090565b60048054611ad490600190613a42565b815481106112be576112be613a55565b6000806000806001600480549050611afc9190613a42565b9050600060048281548110611b1357611b13613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff8082168552700100000000000000000000000000000000918290048116958501869052600183015480821694860194909452928190048316606085015260028201548084166080860152819004831660a0850152600382015492831660c085015267ffffffffffffffff908304811660e085015278010000000000000000000000000000000000000000000000009092049091166101008301526004015463ffffffff80821661012084015264010000000082041661014083015260ff680100000000000000009091041615156101608201529150611c24908290612955565b9450945094505050909192565b606081421115611c6d576040517f203d82d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611c7888611d7a565b5050905086811115611cc0576040517f4c67496b00000000000000000000000000000000000000000000000000000000815260048101889052602481018290526044016106b4565b611d0273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016333084612dd1565b611d0f600089868261181a565b60408051600280825260608201835290916020830190803683370190505091508082600081518110611d4357611d43613a55565b6020026020010181815250508782600181518110611d6357611d63613a55565b602002602001018181525050509695505050505050565b6000806000806001600480549050611d929190613a42565b9050600060048281548110611da957611da9613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff80821661012084015264010000000082041661014083015260ff680100000000000000009091041615156101608201529050611eba8187612955565b91989097509095509350505050565b60048181548110611ed957600080fd5b6000918252602090912060059091020180546001820154600283015460038401546004909401546fffffffffffffffffffffffffffffffff8085169650700100000000000000000000000000000000948590048116958185169594859004821694828516948190048316939282169290820467ffffffffffffffff9081169278010000000000000000000000000000000000000000000000009004169063ffffffff8082169164010000000081049091169068010000000000000000900460ff168c565b6000611fa761288c565b611faf612b2c565b42611fc060c0840160a08501613bc4565b63ffffffff161015611ffe576040517f203d82d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6305f5e1006120106020840184613bdf565b6fffffffffffffffffffffffffffffffff16101561205a576040517fc60f14dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61206a6060830160408401613bdf565b6fffffffffffffffffffffffffffffffff1661208c6040840160208501613bdf565b6fffffffffffffffffffffffffffffffff1610156120d6576040517f501b4f1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120e66060830160408401613bdf565b6fffffffffffffffffffffffffffffffff1615801561211c575061211060a0830160808401613bfa565b67ffffffffffffffff16155b15612153576040517fcdcc1fea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060045480156122bd576000600461216c600184613a42565b8154811061217c5761217c613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff80821661012084015264010000000082041661014083015260ff68010000000000000000909104161580156101608301529091506122bb576040517f800eee7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b604080516101808101909152600490806122da6020860186613bdf565b6fffffffffffffffffffffffffffffffff16815260209081019061230090860186613bdf565b6fffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff1681526020018460200160208101906123759190613bdf565b6fffffffffffffffffffffffffffffffff16815260200161239c6060860160408701613bdf565b6fffffffffffffffffffffffffffffffff1681526020016123c36080860160608701613bfa565b67ffffffffffffffff1681526020016123e260a0860160808701613bfa565b67ffffffffffffffff16815263ffffffff4216602082015260400161240d60c0860160a08701613bc4565b63ffffffff908116825260016020928301819052845480820186556000958652948390208451858501516fffffffffffffffffffffffffffffffff91821670010000000000000000000000000000000091831682021760059098029092019687556040860151606087015190821690821683021792870192909255608085015160a0860151908316908316820217600287015560c085015160038701805460e0880151610100890151939095167fffffffffffffffff0000000000000000000000000000000000000000000000009091161767ffffffffffffffff9485169093029290921777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000939091169290920291909117905561012083015160049094018054610140850151610160909501519583167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909116176401000000009490921693909302177fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000931515939093029290921790557f49f979d434de33c8feec553b9de34d0b7b5ee6a11f0df00c3b60c742ae17f1679082906125ee90850185613bdf565b6125fe6040860160208701613bdf565b61260e6060870160408801613bdf565b61261e6080880160608901613bfa565b61262e60a0890160808a01613bfa565b61263e60c08a0160a08b01613bc4565b604080519788526fffffffffffffffffffffffffffffffff96871660208901529486168786015292909416606086015267ffffffffffffffff908116608086015290921660a084015263ffffffff90911660c0830152519081900360e00190a16126a86001612d79565b61270b33306126ba6020860186613bdf565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169291906fffffffffffffffffffffffffffffffff16612dd1565b6127156001600055565b919050565b60008082610120015163ffffffff16426127349190613a42565b8360e0015167ffffffffffffffff1661274d9190613b5f565b9050808360a001516fffffffffffffffffffffffffffffffff16101561278857505060c001516fffffffffffffffffffffffffffffffff1690565b808360a001516fffffffffffffffffffffffffffffffff166127aa9190613a42565b91508260c001516fffffffffffffffffffffffffffffffff168210156127e4578260c001516fffffffffffffffffffffffffffffffff1691505b50919050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612871576040517fd70f29d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611240836000610f07565b612884612e8e565b61191b612f25565b6002600054036128c8576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600055565b60405173ffffffffffffffffffffffffffffffffffffffff83811660248301526044820183905261295091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612f56565b505050565b6000806000846101600151612996576040517f69b8d0fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84610140015163ffffffff1642106129da576040517f04a5e67c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001516fffffffffffffffffffffffffffffffff16841115612a2a576040517ffc43992200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612a358661271a565b9050670de0b6b3a764000086610100015167ffffffffffffffff1686612a5b9190613b5f565b612a659190613b76565b612a7790670de0b6b3a7640000613a42565b612a818287613b5f565b612a8b9190613b76565b9350670de0b6b3a76400008487610100015167ffffffffffffffff16612ab19190613b5f565b612abb9190613b76565b9250612ac8836002613b5f565b612ad29082613bb1565b9150509250925092565b60006fffffffffffffffffffffffffffffffff821115612b28576040517f35278d1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5090565b61191b33612fec565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa158015612ba2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc69190613ac9565b905082811115610e08576000612bdc8483613a42565b90508215612d51576004805460009190612bf890600190613a42565b81548110612c0857612c08613a55565b906000526020600020906005020190507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603612cd557612c7482612adc565b600182018054600090612c9a9084906fffffffffffffffffffffffffffffffff16613c15565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550612d4f565b612cde82612adc565b600182018054601090612d1890849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613c15565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505b505b612d7273ffffffffffffffffffffffffffffffffffffffff861633836128cf565b5050505050565b612da57f0000000000000000000000000000000000000000000000000000000000000000600083612b35565b61060e7f0000000000000000000000000000000000000000000000000000000000000000600083612b35565b60405173ffffffffffffffffffffffffffffffffffffffff8481166024830152838116604483015260648201839052610e089186918216906323b872dd90608401612909565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600254604051919216907f162998b90abc2507f3953aa797827b03a14c42dbd9a35f09feaf02e0d592773a90600090a350565b61191b33613064565b60025460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc690600090a3600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561191b33612e97565b6000612f7873ffffffffffffffffffffffffffffffffffffffff8416836130dc565b90508051600014158015612f9d575080806020019051810190612f9b9190613c3e565b155b15612950576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016106b4565b60025473ffffffffffffffffffffffffffffffffffffffff82811691161461060e576002546040517f443dc2b400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015290821660248201526044016106b4565b60015473ffffffffffffffffffffffffffffffffffffffff82811691161461060e576001546040517fbe5a953700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015290821660248201526044016106b4565b60606130ea838360006130f3565b90505b92915050565b606081471015613131576040517fcd7860590000000000000000000000000000000000000000000000000000000081523060048201526024016106b4565b6000808573ffffffffffffffffffffffffffffffffffffffff16848660405161315a9190613c5b565b60006040518083038185875af1925050503d8060008114613197576040519150601f19603f3d011682016040523d82523d6000602084013e61319c565b606091505b50915091506131ac8683836131b8565b925050505b9392505050565b6060826131cd576131c882613247565b6131b1565b81511580156131f1575073ffffffffffffffffffffffffffffffffffffffff84163b155b15613240576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016106b4565b50806131b1565b8051156132575780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461271557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610180810167ffffffffffffffff81118282101715613300576133006132ad565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561334d5761334d6132ad565b604052919050565b6000806000806080858703121561336b57600080fd5b84359350602080860135935061338360408701613289565b9250606086013567ffffffffffffffff808211156133a057600080fd5b818801915088601f8301126133b457600080fd5b8135818111156133c6576133c66132ad565b6133f6847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613306565b9150808252898482850101111561340c57600080fd5b808484018584013760008482840101525080935050505092959194509250565b60008060006060848603121561344157600080fd5b505081359360208301359350604090920135919050565b60005b8381101561347357818101518382015260200161345b565b50506000910152565b60008151808452613494816020860160208601613458565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006130ea602083018461347c565b801515811461060e57600080fd5b8035612715816134d9565b6000806040838503121561350557600080fd5b823591506020830135613517816134d9565b809150509250929050565b6000806040838503121561353557600080fd5b8235915061354560208401613289565b90509250929050565b60006020828403121561356057600080fd5b5035919050565b81516fffffffffffffffffffffffffffffffff168152610180810160208301516135a560208401826fffffffffffffffffffffffffffffffff169052565b5060408301516135c960408401826fffffffffffffffffffffffffffffffff169052565b5060608301516135ed60608401826fffffffffffffffffffffffffffffffff169052565b50608083015161361160808401826fffffffffffffffffffffffffffffffff169052565b5060a083015161363560a08401826fffffffffffffffffffffffffffffffff169052565b5060c083015161365960c08401826fffffffffffffffffffffffffffffffff169052565b5060e083015161367560e084018267ffffffffffffffff169052565b506101008381015167ffffffffffffffff16908301526101208084015163ffffffff908116918401919091526101408085015190911690830152610160928301511515929091019190915290565b600080600080600060a086880312156136db57600080fd5b853594506020808701359450604087013567ffffffffffffffff8082111561370257600080fd5b818901915089601f83011261371657600080fd5b813581811115613728576137286132ad565b8060051b9150613739848301613306565b818152918301840191848101908c84111561375357600080fd5b938501935b838510156137785761376985613289565b82529385019390850190613758565b80985050505050505061378d60608701613289565b949793965091946080013592915050565b6020808252825182820181905260009190848201906040850190845b818110156137d6578351835292840192918401916001016137ba565b50909695505050505050565b6000602082840312156137f457600080fd5b6130ea82613289565b6000806040838503121561381057600080fd5b61381983613289565b915061354560208401613289565b60008060008060008060a0878903121561384057600080fd5b8635955060208701359450604087013567ffffffffffffffff8082111561386657600080fd5b818901915089601f83011261387a57600080fd5b81358181111561388957600080fd5b8a60208260051b850101111561389e57600080fd5b6020830196508095505050506138b660608801613289565b9150608087013590509295509295509295565b600060c082840312156127e457600080fd5b80356fffffffffffffffffffffffffffffffff8116811461271557600080fd5b803567ffffffffffffffff8116811461271557600080fd5b803563ffffffff8116811461271557600080fd5b6000610180828403121561393a57600080fd5b6139426132dc565b61394b836138db565b8152613959602084016138db565b602082015261396a604084016138db565b604082015261397b606084016138db565b606082015261398c608084016138db565b608082015261399d60a084016138db565b60a08201526139ae60c084016138db565b60c08201526139bf60e084016138fb565b60e08201526101006139d28185016138fb565b908201526101206139e4848201613913565b908201526101406139f6848201613913565b90820152610160613a088482016134e7565b908201529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156130ed576130ed613a13565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152826040820152608060608201526000613abf608083018461347c565b9695505050505050565b600060208284031215613adb57600080fd5b5051919050565b6fffffffffffffffffffffffffffffffff828116828216039080821115613b0b57613b0b613a13565b5092915050565b600181811c90821680613b2657607f821691505b6020821081036127e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b80820281158282048414176130ed576130ed613a13565b600082613bac577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808201808211156130ed576130ed613a13565b600060208284031215613bd657600080fd5b6130ea82613913565b600060208284031215613bf157600080fd5b6130ea826138db565b600060208284031215613c0c57600080fd5b6130ea826138fb565b6fffffffffffffffffffffffffffffffff818116838216019080821115613b0b57613b0b613a13565b600060208284031215613c5057600080fd5b81516131b1816134d9565b60008251613c6d818460208701613458565b919091019291505056fea26469706673582212208ec73c478f099ff03b90c422145c33e3f767a8e355a0920077a210d2face11b464736f6c6343000818003300000000000000000000000055271b0d4dac2664fa9d44f8cccd89a3e6342313000000000000000000000000fc000000000000000000000000000000000000010000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102ad5760003560e01c80635909c0d51161017b578063aaf5eb68116100d8578063d21220a71161008c578063f140a35a11610071578063f140a35a14610653578063f6ccaad414610666578063fff6cae9146102c557600080fd5b8063d21220a714610619578063e40dc7031461064057600080fd5b8063ba9a7a56116100bd578063ba9a7a56146104d6578063bc25cf7714610600578063c45a01551461061157600080fd5b8063aaf5eb68146105de578063afa29031146105ed57600080fd5b80637464fc3d1161012f5780638803dbee116101145780638803dbee146105155780639b4faa8014610528578063a005ec7a1461053b57600080fd5b80637464fc3d146104d657806385f8c259146102c757600080fd5b80635c80aeee116101605780635c80aeee146104de5780635f28bc5b146105055780636df00be81461050d57600080fd5b80635909c0d5146104d65780635a3d5493146104d657600080fd5b8063269b9a08116102295780634bc66f32116101dd57806354fd4d50116101c257806354fd4d50146104bc57806355d256e9146104c6578063561ad39f146104ce57600080fd5b80634bc66f32146104945780634f8b4ae7146104b457600080fd5b8063450140951161020e5780634501409514610447578063485cc9551461045a5780634b4349d51461046d57600080fd5b8063269b9a081461040a57806338ed17391461042757600080fd5b8063090f3f501161028057806311106ee21161026557806311106ee2146103a95780631125f13f146103d7578063241a277f146103ea57600080fd5b8063090f3f501461033d5780630dfe16811461038257600080fd5b8063022c0d9f146102b2578063054d50d4146102c757806306fdde03146102ed5780630902f1ac14610302575b600080fd5b6102c56102c0366004613355565b61066e565b005b6102da6102d536600461342c565b610e0e565b6040519081526020015b60405180910390f35b6102f5610e42565b6040516102e491906134c6565b61030a610ed0565b604080516dffffffffffffffffffffffffffff948516815293909216602084015263ffffffff16908201526060016102e4565b60015461035d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102e4565b61035d7f000000000000000000000000fc0000000000000000000000000000000000000181565b6103bc6103b73660046134f2565b610f07565b604080519384526020840192909252908201526060016102e4565b6102da6103e5366004613522565b6111b0565b6103fd6103f836600461354e565b61124a565b6040516102e49190613567565b6104126113c9565b604080519283526020830191909152016102e4565b61043a6104353660046136c3565b61173e565b6040516102e4919061379e565b6102c56104553660046137e2565b6118b4565b6102c56104683660046137fd565b6118c5565b61035d7f000000000000000000000000fc0000000000000000000000000000000000000181565b60025461035d9073ffffffffffffffffffffffffffffffffffffffff1681565b6102c56118f7565b60016000816103bc565b6102da61191d565b6004546102da565b6102da610e0e565b61035d7f0000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e81565b6103fd611a53565b6103bc611ae4565b61043a610523366004613827565b611c31565b6103bc61053636600461354e565b611d7a565b61054e61054936600461354e565b611ec9565b604080516fffffffffffffffffffffffffffffffff9d8e1681529b8d1660208d0152998c16998b0199909952968a1660608a0152948916608089015292881660a0880152961660c086015267ffffffffffffffff95861660e08601529490941661010084015263ffffffff93841661012084015292909216610140820152901515610160820152610180016102e4565b6102da670de0b6b3a764000081565b6102da6105fb3660046138c9565b611f9d565b6102c561060e3660046137e2565b50565b61035d610e0e565b61035d7f0000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e81565b6102da61064e366004613927565b61271a565b6102da610661366004613522565b6127ea565b6102c561287c565b61067661288c565b83156106bd576040517f0ed4217800000000000000000000000000000000000000000000000000000000815260006004820152602481018590526044015b60405180910390fd5b82600003610701576040517fd28d3eb500000000000000000000000000000000000000000000000000000000815260016004820152600060248201526044016106b4565b60045460009061071390600190613a42565b905060006004828154811061072a5761072a613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff8082166101208401526401000000008204811661014084015260ff6801000000000000000090920491909116151561016083015290915061087c9073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e1690869088906128cf16565b82511561090e576040517f10d1e85c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516906310d1e85c906108db9033908a908a908990600401613a84565b600060405180830381600087803b1580156108f557600080fd5b505af1158015610909573d6000803e3d6000fd5b505050505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000907f000000000000000000000000fc0000000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa15801561099b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109bf9190613ac9565b9050600082608001516fffffffffffffffffffffffffffffffff16826109e59190613a42565b6040805182815260006020820181905281830152606081018a9052905191925073ffffffffffffffffffffffffffffffffffffffff88169133917fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822919081900360800190a36000806000610a59868b612955565b92509250925082841015610aa3576040517fec3e79fb00000000000000000000000000000000000000000000000000000000815260048101849052602481018590526044016106b4565b82600003610add576040517f55eaa09500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ae68a612adc565b86602001818151610af79190613ae2565b6fffffffffffffffffffffffffffffffff16905250610b1585612adc565b6fffffffffffffffffffffffffffffffff166080870152610b3581612adc565b6fffffffffffffffffffffffffffffffff1660a087015263ffffffff42166101208701526004805487919089908110610b7057610b70613a55565b60009182526020918290208351928401516fffffffffffffffffffffffffffffffff9081167001000000000000000000000000000000009081029482169490941760059093029091019182556040840151606085015182168402908216176001830155608084015160a08501518216840290821617600283015560c084015160038301805460e087015161010088015167ffffffffffffffff90811678010000000000000000000000000000000000000000000000000277ffffffffffffffffffffffffffffffffffffffffffffffff919092169097027fffffffffffffffff00000000000000000000000000000000000000000000000090921693909416929092179190911793909316179091556101208201516004909101805461014084015161016090940151151568010000000000000000027fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff63ffffffff958616640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909316959094169490941717919091169190911790557f4c8e97934cb2d5c0876fe70b82782d28160e62ef5844aa6ba80e10174feed687877f000000000000000000000000fc000000000000000000000000000000000000017f0000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e610d7a88612adc565b610d838f612adc565b8b60a00151610d9189612adc565b6040805197885273ffffffffffffffffffffffffffffffffffffffff968716602089015294909516868501526fffffffffffffffffffffffffffffffff92831660608701529082166080860152811660a085015290911660c0830152519081900360e00190a150505050505050610e086001600055565b50505050565b60006040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60038054610e4f90613b12565b80601f0160208091040260200160405190810160405280929190818152602001828054610e7b90613b12565b8015610ec85780601f10610e9d57610100808354040283529160200191610ec8565b820191906000526020600020905b815481529060010190602001808311610eab57829003601f168201915b505050505081565b60008060006040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000806001600480549050610f1f9190613a42565b9050600060048281548110610f3657610f36613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff80821661012084015264010000000082041661014083015260ff680100000000000000009091041615156101608201819052909150611076576040517f69b8d0fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80610140015163ffffffff1642106110ba576040517f04a5e67c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006110c58261271a565b9050670de0b6b3a76400008883610100015167ffffffffffffffff166110eb9190613b5f565b6110f59190613b76565b94506111018582613bb1565b611113670de0b6b3a76400008a613b5f565b61111d9190613b76565b955081602001516fffffffffffffffffffffffffffffffff1686111561118f578615611175576040517ffc43992200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b81602001516fffffffffffffffffffffffffffffffff1695505b61119a856002613b5f565b6111a49082613bb1565b93505050509250925092565b60007f0000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614611237576040517f1b6d1fa000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61124083611d7a565b5090949350505050565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081018290526101408101829052610160810191909152600482815481106112be576112be613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff80821661012084015264010000000082041661014083015260ff6801000000000000000090910416151561016082015292915050565b6000806113d461288c565b6113dc612b2c565b6004546000906113ee90600190613a42565b905060006004828154811061140557611405613a55565b906000526020600020906005020190508060040160089054906101000a900460ff1661145d576040517f69b8d0fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028101546114a1907f000000000000000000000000fc00000000000000000000000000000000000001906fffffffffffffffffffffffffffffffff166001612b35565b80546114f6907f0000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff166001612b35565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000fc0000000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611580573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a49190613ac9565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529094507f0000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e73ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015611631573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116559190613ac9565b6004820180547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1690556002820180546fffffffffffffffffffffffffffffffff8088167fffffffffffffffffffffffffffffffff0000000000000000000000000000000090921691909117909155825481831670010000000000000000000000000000000002911617825592506116ed6000612d79565b60408051838152602081018690529081018490527fdeb58d7180330f713ed3023619d340a8f4f264aee7cd0707f8997ce863182e999060600160405180910390a1505061173a6001600055565b9091565b60608142111561177a576040517f203d82d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611787876001610f07565b50509050858110156117cf576040517fd28d3eb500000000000000000000000000000000000000000000000000000000815260048101879052602481018290526044016106b4565b61181173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000fc000000000000000000000000000000000000011633308a612dd1565b61184a60008286825b6040519080825280601f01601f191660200182016040528015611844576020820181803683370190505b5061066e565b6040805160028082526060820183529091602083019080368337019050509150868260008151811061187e5761187e613a55565b602002602001018181525050808260018151811061189e5761189e613a55565b6020026020010181815250505095945050505050565b6118bc612b2c565b61060e81612e17565b6040517fd623472500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6118ff612b2c565b611907612e8e565b6119116000612e17565b61191b6000612e97565b565b60048054600091611a4e9161193490600190613a42565b8154811061194457611944613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff80821661012084015264010000000082041661014083015260ff6801000000000000000090910416151561016082015261271a565b905090565b6040805161018081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e081018290526101008101829052610120810182905261014081018290526101608101919091526004546000819003611ac4575090565b60048054611ad490600190613a42565b815481106112be576112be613a55565b6000806000806001600480549050611afc9190613a42565b9050600060048281548110611b1357611b13613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff8082168552700100000000000000000000000000000000918290048116958501869052600183015480821694860194909452928190048316606085015260028201548084166080860152819004831660a0850152600382015492831660c085015267ffffffffffffffff908304811660e085015278010000000000000000000000000000000000000000000000009092049091166101008301526004015463ffffffff80821661012084015264010000000082041661014083015260ff680100000000000000009091041615156101608201529150611c24908290612955565b9450945094505050909192565b606081421115611c6d576040517f203d82d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000611c7888611d7a565b5050905086811115611cc0576040517f4c67496b00000000000000000000000000000000000000000000000000000000815260048101889052602481018290526044016106b4565b611d0273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000fc0000000000000000000000000000000000000116333084612dd1565b611d0f600089868261181a565b60408051600280825260608201835290916020830190803683370190505091508082600081518110611d4357611d43613a55565b6020026020010181815250508782600181518110611d6357611d63613a55565b602002602001018181525050509695505050505050565b6000806000806001600480549050611d929190613a42565b9050600060048281548110611da957611da9613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff80821661012084015264010000000082041661014083015260ff680100000000000000009091041615156101608201529050611eba8187612955565b91989097509095509350505050565b60048181548110611ed957600080fd5b6000918252602090912060059091020180546001820154600283015460038401546004909401546fffffffffffffffffffffffffffffffff8085169650700100000000000000000000000000000000948590048116958185169594859004821694828516948190048316939282169290820467ffffffffffffffff9081169278010000000000000000000000000000000000000000000000009004169063ffffffff8082169164010000000081049091169068010000000000000000900460ff168c565b6000611fa761288c565b611faf612b2c565b42611fc060c0840160a08501613bc4565b63ffffffff161015611ffe576040517f203d82d800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6305f5e1006120106020840184613bdf565b6fffffffffffffffffffffffffffffffff16101561205a576040517fc60f14dd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61206a6060830160408401613bdf565b6fffffffffffffffffffffffffffffffff1661208c6040840160208501613bdf565b6fffffffffffffffffffffffffffffffff1610156120d6576040517f501b4f1500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6120e66060830160408401613bdf565b6fffffffffffffffffffffffffffffffff1615801561211c575061211060a0830160808401613bfa565b67ffffffffffffffff16155b15612153576040517fcdcc1fea00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5060045480156122bd576000600461216c600184613a42565b8154811061217c5761217c613a55565b60009182526020918290206040805161018081018252600590930290910180546fffffffffffffffffffffffffffffffff808216855270010000000000000000000000000000000091829004811695850195909552600182015480861693850193909352918290048416606084015260028101548085166080850152829004841660a0840152600381015493841660c084015267ffffffffffffffff918404821660e084015278010000000000000000000000000000000000000000000000009093041661010082015260049091015463ffffffff80821661012084015264010000000082041661014083015260ff68010000000000000000909104161580156101608301529091506122bb576040517f800eee7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505b604080516101808101909152600490806122da6020860186613bdf565b6fffffffffffffffffffffffffffffffff16815260209081019061230090860186613bdf565b6fffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff16815260200160006fffffffffffffffffffffffffffffffff1681526020018460200160208101906123759190613bdf565b6fffffffffffffffffffffffffffffffff16815260200161239c6060860160408701613bdf565b6fffffffffffffffffffffffffffffffff1681526020016123c36080860160608701613bfa565b67ffffffffffffffff1681526020016123e260a0860160808701613bfa565b67ffffffffffffffff16815263ffffffff4216602082015260400161240d60c0860160a08701613bc4565b63ffffffff908116825260016020928301819052845480820186556000958652948390208451858501516fffffffffffffffffffffffffffffffff91821670010000000000000000000000000000000091831682021760059098029092019687556040860151606087015190821690821683021792870192909255608085015160a0860151908316908316820217600287015560c085015160038701805460e0880151610100890151939095167fffffffffffffffff0000000000000000000000000000000000000000000000009091161767ffffffffffffffff9485169093029290921777ffffffffffffffffffffffffffffffffffffffffffffffff167801000000000000000000000000000000000000000000000000939091169290920291909117905561012083015160049094018054610140850151610160909501519583167fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909116176401000000009490921693909302177fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff1668010000000000000000931515939093029290921790557f49f979d434de33c8feec553b9de34d0b7b5ee6a11f0df00c3b60c742ae17f1679082906125ee90850185613bdf565b6125fe6040860160208701613bdf565b61260e6060870160408801613bdf565b61261e6080880160608901613bfa565b61262e60a0890160808a01613bfa565b61263e60c08a0160a08b01613bc4565b604080519788526fffffffffffffffffffffffffffffffff96871660208901529486168786015292909416606086015267ffffffffffffffff908116608086015290921660a084015263ffffffff90911660c0830152519081900360e00190a16126a86001612d79565b61270b33306126ba6020860186613bdf565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e169291906fffffffffffffffffffffffffffffffff16612dd1565b6127156001600055565b919050565b60008082610120015163ffffffff16426127349190613a42565b8360e0015167ffffffffffffffff1661274d9190613b5f565b9050808360a001516fffffffffffffffffffffffffffffffff16101561278857505060c001516fffffffffffffffffffffffffffffffff1690565b808360a001516fffffffffffffffffffffffffffffffff166127aa9190613a42565b91508260c001516fffffffffffffffffffffffffffffffff168210156127e4578260c001516fffffffffffffffffffffffffffffffff1691505b50919050565b60007f000000000000000000000000fc0000000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614612871576040517fd70f29d200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611240836000610f07565b612884612e8e565b61191b612f25565b6002600054036128c8576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6002600055565b60405173ffffffffffffffffffffffffffffffffffffffff83811660248301526044820183905261295091859182169063a9059cbb906064015b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050612f56565b505050565b6000806000846101600151612996576040517f69b8d0fe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84610140015163ffffffff1642106129da576040517f04a5e67c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84602001516fffffffffffffffffffffffffffffffff16841115612a2a576040517ffc43992200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612a358661271a565b9050670de0b6b3a764000086610100015167ffffffffffffffff1686612a5b9190613b5f565b612a659190613b76565b612a7790670de0b6b3a7640000613a42565b612a818287613b5f565b612a8b9190613b76565b9350670de0b6b3a76400008487610100015167ffffffffffffffff16612ab19190613b5f565b612abb9190613b76565b9250612ac8836002613b5f565b612ad29082613bb1565b9150509250925092565b60006fffffffffffffffffffffffffffffffff821115612b28576040517f35278d1200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5090565b61191b33612fec565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260009073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa158015612ba2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bc69190613ac9565b905082811115610e08576000612bdc8483613a42565b90508215612d51576004805460009190612bf890600190613a42565b81548110612c0857612c08613a55565b906000526020600020906005020190507f000000000000000000000000fc0000000000000000000000000000000000000173ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff1603612cd557612c7482612adc565b600182018054600090612c9a9084906fffffffffffffffffffffffffffffffff16613c15565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff160217905550612d4f565b612cde82612adc565b600182018054601090612d1890849070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16613c15565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff1602179055505b505b612d7273ffffffffffffffffffffffffffffffffffffffff861633836128cf565b5050505050565b612da57f000000000000000000000000fc00000000000000000000000000000000000001600083612b35565b61060e7f0000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e600083612b35565b60405173ffffffffffffffffffffffffffffffffffffffff8481166024830152838116604483015260648201839052610e089186918216906323b872dd90608401612909565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255600254604051919216907f162998b90abc2507f3953aa797827b03a14c42dbd9a35f09feaf02e0d592773a90600090a350565b61191b33613064565b60025460405173ffffffffffffffffffffffffffffffffffffffff8084169216907f31b6c5a04b069b6ec1b3cef44c4e7c1eadd721349cda9823d0b1877b3551cdc690600090a3600280547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905561191b33612e97565b6000612f7873ffffffffffffffffffffffffffffffffffffffff8416836130dc565b90508051600014158015612f9d575080806020019051810190612f9b9190613c3e565b155b15612950576040517f5274afe700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201526024016106b4565b60025473ffffffffffffffffffffffffffffffffffffffff82811691161461060e576002546040517f443dc2b400000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015290821660248201526044016106b4565b60015473ffffffffffffffffffffffffffffffffffffffff82811691161461060e576001546040517fbe5a953700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015290821660248201526044016106b4565b60606130ea838360006130f3565b90505b92915050565b606081471015613131576040517fcd7860590000000000000000000000000000000000000000000000000000000081523060048201526024016106b4565b6000808573ffffffffffffffffffffffffffffffffffffffff16848660405161315a9190613c5b565b60006040518083038185875af1925050503d8060008114613197576040519150601f19603f3d011682016040523d82523d6000602084013e61319c565b606091505b50915091506131ac8683836131b8565b925050505b9392505050565b6060826131cd576131c882613247565b6131b1565b81511580156131f1575073ffffffffffffffffffffffffffffffffffffffff84163b155b15613240576040517f9996b31500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff851660048201526024016106b4565b50806131b1565b8051156132575780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b803573ffffffffffffffffffffffffffffffffffffffff8116811461271557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051610180810167ffffffffffffffff81118282101715613300576133006132ad565b60405290565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561334d5761334d6132ad565b604052919050565b6000806000806080858703121561336b57600080fd5b84359350602080860135935061338360408701613289565b9250606086013567ffffffffffffffff808211156133a057600080fd5b818801915088601f8301126133b457600080fd5b8135818111156133c6576133c66132ad565b6133f6847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601613306565b9150808252898482850101111561340c57600080fd5b808484018584013760008482840101525080935050505092959194509250565b60008060006060848603121561344157600080fd5b505081359360208301359350604090920135919050565b60005b8381101561347357818101518382015260200161345b565b50506000910152565b60008151808452613494816020860160208601613458565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006130ea602083018461347c565b801515811461060e57600080fd5b8035612715816134d9565b6000806040838503121561350557600080fd5b823591506020830135613517816134d9565b809150509250929050565b6000806040838503121561353557600080fd5b8235915061354560208401613289565b90509250929050565b60006020828403121561356057600080fd5b5035919050565b81516fffffffffffffffffffffffffffffffff168152610180810160208301516135a560208401826fffffffffffffffffffffffffffffffff169052565b5060408301516135c960408401826fffffffffffffffffffffffffffffffff169052565b5060608301516135ed60608401826fffffffffffffffffffffffffffffffff169052565b50608083015161361160808401826fffffffffffffffffffffffffffffffff169052565b5060a083015161363560a08401826fffffffffffffffffffffffffffffffff169052565b5060c083015161365960c08401826fffffffffffffffffffffffffffffffff169052565b5060e083015161367560e084018267ffffffffffffffff169052565b506101008381015167ffffffffffffffff16908301526101208084015163ffffffff908116918401919091526101408085015190911690830152610160928301511515929091019190915290565b600080600080600060a086880312156136db57600080fd5b853594506020808701359450604087013567ffffffffffffffff8082111561370257600080fd5b818901915089601f83011261371657600080fd5b813581811115613728576137286132ad565b8060051b9150613739848301613306565b818152918301840191848101908c84111561375357600080fd5b938501935b838510156137785761376985613289565b82529385019390850190613758565b80985050505050505061378d60608701613289565b949793965091946080013592915050565b6020808252825182820181905260009190848201906040850190845b818110156137d6578351835292840192918401916001016137ba565b50909695505050505050565b6000602082840312156137f457600080fd5b6130ea82613289565b6000806040838503121561381057600080fd5b61381983613289565b915061354560208401613289565b60008060008060008060a0878903121561384057600080fd5b8635955060208701359450604087013567ffffffffffffffff8082111561386657600080fd5b818901915089601f83011261387a57600080fd5b81358181111561388957600080fd5b8a60208260051b850101111561389e57600080fd5b6020830196508095505050506138b660608801613289565b9150608087013590509295509295509295565b600060c082840312156127e457600080fd5b80356fffffffffffffffffffffffffffffffff8116811461271557600080fd5b803567ffffffffffffffff8116811461271557600080fd5b803563ffffffff8116811461271557600080fd5b6000610180828403121561393a57600080fd5b6139426132dc565b61394b836138db565b8152613959602084016138db565b602082015261396a604084016138db565b604082015261397b606084016138db565b606082015261398c608084016138db565b608082015261399d60a084016138db565b60a08201526139ae60c084016138db565b60c08201526139bf60e084016138fb565b60e08201526101006139d28185016138fb565b908201526101206139e4848201613913565b908201526101406139f6848201613913565b90820152610160613a088482016134e7565b908201529392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156130ed576130ed613a13565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff85168152836020820152826040820152608060608201526000613abf608083018461347c565b9695505050505050565b600060208284031215613adb57600080fd5b5051919050565b6fffffffffffffffffffffffffffffffff828116828216039080821115613b0b57613b0b613a13565b5092915050565b600181811c90821680613b2657607f821691505b6020821081036127e4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b80820281158282048414176130ed576130ed613a13565b600082613bac577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b808201808211156130ed576130ed613a13565b600060208284031215613bd657600080fd5b6130ea82613913565b600060208284031215613bf157600080fd5b6130ea826138db565b600060208284031215613c0c57600080fd5b6130ea826138fb565b6fffffffffffffffffffffffffffffffff818116838216019080821115613b0b57613b0b613a13565b600060208284031215613c5057600080fd5b81516131b1816134d9565b60008251613c6d818460208701613458565b919091019291505056fea26469706673582212208ec73c478f099ff03b90c422145c33e3f767a8e355a0920077a210d2face11b464736f6c63430008180033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000055271b0d4dac2664fa9d44f8cccd89a3e6342313000000000000000000000000fc000000000000000000000000000000000000010000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e
-----Decoded View---------------
Arg [0] : _timelock (address): 0x55271b0d4DaC2664Fa9d44F8cccd89A3e6342313
Arg [1] : _tokenBuy (address): 0xFc00000000000000000000000000000000000001
Arg [2] : _tokenSell (address): 0x8e9C334afc76106F08E0383907F4Fca9bB10BA3e
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 00000000000000000000000055271b0d4dac2664fa9d44f8cccd89a3e6342313
Arg [1] : 000000000000000000000000fc00000000000000000000000000000000000001
Arg [2] : 0000000000000000000000008e9c334afc76106f08e0383907f4fca9bb10ba3e
Deployed Bytecode Sourcemap
1565:32586:10:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20800:2563;;;;;;:::i;:::-;;:::i;:::-;;13064:121;;;;;;:::i;:::-;;:::i;:::-;;;2505:25:12;;;2493:2;2478:18;13064:121:10;;;;;;;;1892:18;;;:::i;:::-;;;;;;;:::i;13317:112::-;;;:::i;:::-;;;;3665:30:12;3722:15;;;3704:34;;3774:15;;;;3769:2;3754:18;;3747:43;3838:10;3826:23;3806:18;;;3799:51;3643:2;3628:18;13317:112:10;3455:401:12;1358:37:9;;;;;;;;;;;;4037:42:12;4025:55;;;4007:74;;3995:2;3980:18;1358:37:9;3861:226:12;2342:31:10;;;;;6724:1435;;;;;;:::i;:::-;;:::i;:::-;;;;4864:25:12;;;4920:2;4905:18;;4898:34;;;;4948:18;;;4941:34;4852:2;4837:18;6724:1435:10;4662:319:12;12078:230:10;;;;;;:::i;:::-;;:::i;14197:134::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;18729:1386::-;;;:::i;:::-;;;;7576:25:12;;;7632:2;7617:18;;7610:34;;;;7549:18;18729:1386:10;7402:248:12;23949:1067:10;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2029:149:9:-;;;;;;:::i;:::-;;:::i;13954:92:10:-;;;;;;:::i;:::-;;:::i;2134:34::-;;;;;1447:30:9;;;;;;;;;2710:204;;;:::i;5110:123:10:-;5218:1;5152:14;5218:1;5110:123;;6121:135;;;:::i;14449:106::-;14534:7;:14;14449:106;;13435:104;;;:::i;2221:35::-;;;;;14723:233;;;:::i;8525:472::-;;;:::i;25602:1004::-;;;;;;:::i;:::-;;:::i;9417:529::-;;;;;;:::i;:::-;;:::i;2048:23::-;;;;;;:::i;:::-;;:::i;:::-;;;;11338:34:12;11399:15;;;11381:34;;11451:15;;;11446:2;11431:18;;11424:43;11503:15;;;11483:18;;;11476:43;;;;11555:15;;;11550:2;11535:18;;11528:43;11608:15;;;11602:3;11587:19;;11580:44;11661:15;;;11655:3;11640:19;;11633:44;11714:15;;11708:3;11693:19;;11686:44;11779:18;11767:31;;;11761:3;11746:19;;11739:60;5619:30;;;;11849:3;11834:19;;5607:43;3432:10;3421:22;;;11904:3;11889:19;;3409:35;3421:22;;;;11960:3;11945:19;;3409:35;5731:13;;5724:21;12014:3;11999:19;;5712:34;11315:3;11300:19;2048:23:10;10885:1140:12;1952:40:10;;1988:4;1952:40;;16035:2457;;;;;;:::i;:::-;;:::i;12896:60::-;;;;;;:::i;:::-;2029:149:9;;13750:91:10;;;:::i;2463:31::-;;;;;5431:581;;;;;;:::i;:::-;;:::i;12588:259::-;;;;;;:::i;:::-;;:::i;2326:136:9:-;;;:::i;20800:2563:10:-;2356:21:8;:19;:21::i;:::-;20919:15:10;;20915:86:::1;;20943:58;::::0;::::1;::::0;;20974:1:::1;20943:58;::::0;::::1;7576:25:12::0;7617:18;;;7610:34;;;7549:18;;20943:58:10::1;;;;;;;;20915:86;21015:10;21029:1;21015:15:::0;21011:81:::1;;21039:53;::::0;::::1;::::0;;21074:1:::1;21039:53;::::0;::::1;7576:25:12::0;21088:1:10::1;7617:18:12::0;;;7610:34;7549:18;;21039:53:10::1;7402:248:12::0;21011:81:10::1;21195:7;:14:::0;21170:22:::1;::::0;21195:18:::1;::::0;21212:1:::1;::::0;21195:18:::1;:::i;:::-;21170:43;;21223:20;21246:7;21254:14;21246:23;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;21223:46:::1;::::0;;::::1;::::0;::::1;::::0;;21246:23:::1;::::0;;::::1;::::0;;::::1;21223:46:::0;;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;;;::::1;::::0;;;;;;;;;;::::1;::::0;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;::::1;;;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;;;::::0;;;;;;-1:-1:-1;21307:47:10::1;::::0;:31:::1;21314:10;21307:31;::::0;21339:2;;21343:10;;21307:31:::1;:47;:::i;:::-;21417:11:::0;;:15;21413:234:::1;;21448:188;::::0;;;;:34:::1;::::0;::::1;::::0;::::1;::::0;:188:::1;::::0;21509:10:::1;::::0;21546;;21583;;21617:4;;21448:188:::1;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;21413:234;21732:42;::::0;;;;21768:4:::1;21732:42;::::0;::::1;4007:74:12::0;21705:24:10::1;::::0;21739:9:::1;21732:27;;::::0;::::1;::::0;3980:18:12;;21732:42:10::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;21705:69;;21784:19;21825:6;:23;;;21806:42;;:16;:42;;;;:::i;:::-;21952:193;::::0;;15900:25:12;;;22050:1:10::1;15956:2:12::0;15941:18;;15934:34;;;15984:18;;;15977:34;16042:2;16027:18;;16020:34;;;21952:193:10;;15900:25:12;;-1:-1:-1;21952:193:10::1;::::0;::::1;::::0;21979:10:::1;::::0;21952:193:::1;::::0;;;;;15887:3:12;21952:193:10;;::::1;22210:20;22232:29:::0;22263:26:::1;22293:88;22329:6;22360:10;22293:12;:88::i;:::-;22209:172;;;;;;22438:12;22424:11;:26;22420:110;;;22459:71;::::0;::::1;::::0;;::::1;::::0;::::1;7576:25:12::0;;;7617:18;;;7610:34;;;7549:18;;22459:71:10::1;7402:248:12::0;22420:110:10::1;22544:12;22560:1;22544:17:::0;22540:47:::1;;22570:17;;;;;;;;;;;;;;22540:47;22676:23;22688:10;22676:11;:23::i;:::-;22655:6;:17;;:44;;;;;;;:::i;:::-;;;::::0;;-1:-1:-1;22735:29:10::1;22747:16:::0;22735:11:::1;:29::i;:::-;22709:55;;:23;::::0;::::1;:55:::0;22793:31:::1;22805:18:::0;22793:11:::1;:31::i;:::-;22774:50;;:16;::::0;::::1;:50:::0;22834:44:::1;22862:15;22834:44;:18;::::0;::::1;:44:::0;22949:7:::1;:23:::0;;22774:6;;22949:7;22957:14;;22949:23;::::1;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;:32;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;::::1;::::0;;;::::1;:23;::::0;;::::1;::::0;;::::1;:32:::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;;;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;::::1;::::0;;;;;;;::::1;::::0;;;;;;;::::1;::::0;;;::::1;;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;23023:333:::1;23056:14:::0;23094:9:::1;23128:10;23162:24;23174:11:::0;23162::::1;:24::i;:::-;23211:23;23223:10;23211:11;:23::i;:::-;23259:6;:16;;;23311:34;23323:21;23311:11;:34::i;:::-;23023:333;::::0;;16585:25:12;;;16629:42;16707:15;;;16702:2;16687:18;;16680:43;16759:15;;;;16739:18;;;16732:43;16794:34;16864:15;;;16859:2;16844:18;;16837:43;16917:15;;;16911:3;16896:19;;16889:44;16970:15;;16964:3;16949:19;;16942:44;17023:15;;;17017:3;17002:19;;16995:44;23023:333:10;;;;;16572:3:12;23023:333:10;;::::1;20905:2458;;;;;;;2398:20:8::0;1713:1;2924:7;:21;2744:208;2398:20;20800:2563:10;;;;:::o;13064:121::-;13136:7;13162:16;;;;;;;;;;;;;;1892:18;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;13317:112::-;13363:7;13372;13381:6;13406:16;;;;;;;;;;;;;;6724:1435;6837:17;6856:29;6887:26;6959:22;7001:1;6984:7;:14;;;;:18;;;;:::i;:::-;6959:43;;7045:21;7069:7;7077:14;7069:23;;;;;;;;:::i;:::-;;;;;;;;;;7045:47;;;;;;;;7069:23;;;;;;;7045:47;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;7159:46:10;;7187:18;;;;;;;;;;;;;;7159:46;7238:7;:14;;;7219:33;;:15;:33;7215:62;;7261:16;;;;;;;;;;;;;;7215:62;7381:25;7409:41;7440:7;7409:19;:41::i;:::-;7381:69;;1988:4;7595:8;7571:7;:21;;;:32;;;;;;:::i;:::-;7570:46;;;;:::i;:::-;7546:70;-1:-1:-1;7717:41:10;7546:70;7717:17;:41;:::i;:::-;7692:20;1988:4;7692:8;:20;:::i;:::-;7691:68;;;;:::i;:::-;7679:80;;7845:7;:18;;;7833:30;;:9;:30;7829:179;;;7883:23;7879:118;;;7915:33;;;;;;;;;;;;;;7879:118;7979:7;:18;;;7967:30;;;;7879:118;8088:25;8092:21;8088:1;:25;:::i;:::-;8067:47;;:17;:47;:::i;:::-;8046:68;;6915:1244;;;6724:1435;;;;;:::o;12078:230::-;12157:16;12201:10;12189:22;;:8;:22;;;12185:52;;12220:17;;;;;;;;;;;;;;12185:52;12264:37;12289:9;12264:11;:37::i;:::-;-1:-1:-1;12247:54:10;;12078:230;-1:-1:-1;;;;12078:230:10:o;14197:134::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14301:7:10;14309:14;14301:23;;;;;;;;:::i;:::-;;;;;;;;;;14294:30;;;;;;;;14301:23;;;;;;;14294:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14197:134;-1:-1:-1;;14197:134:10:o;18729:1386::-;18781:24;18807:26;2356:21:8;:19;:21::i;:::-;18845:26:10::1;:24;:26::i;:::-;18958:7;:14:::0;18933:22:::1;::::0;18958:18:::1;::::0;18975:1:::1;::::0;18958:18:::1;:::i;:::-;18933:43;;18986:21;19010:7;19018:14;19010:23;;;;;;;;:::i;:::-;;;;;;;;;;;18986:47;;19048:6;:13;;;;;;;;;;;;19043:45;;19070:18;;;;;;;;;;;;;;19043:45;19259:23;::::0;::::1;::::0;19199:101:::1;::::0;19233:9:::1;::::0;19259:23:::1;;::::0;19199::::1;:101::i;:::-;19371:17:::0;;19310:96:::1;::::0;19344:10:::1;::::0;19371:17;;::::1;;;19399:4;19310:23;:96::i;:::-;19465:42;::::0;;;;19501:4:::1;19465:42;::::0;::::1;4007:74:12::0;19472:9:10::1;19465:27;;::::0;::::1;::::0;3980:18:12;;19465:42:10::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;19538:43;::::0;;;;19575:4:::1;19538:43;::::0;::::1;4007:74:12::0;19446:61:10;;-1:-1:-1;19545:10:10::1;19538:28;;::::0;::::1;::::0;3980:18:12;;19538:43:10::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;19646:13;::::0;::::1;:21:::0;;;::::1;::::0;;19677:23:::1;::::0;::::1;:51:::0;;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;19738:47;;;;::::1;::::0;::::1;::::0;::::1;;::::0;;19517:64;-1:-1:-1;19876:47:10::1;19662:5;19876:27;:47::i;:::-;19939:169;::::0;;4864:25:12;;;4920:2;4905:18;;4898:34;;;4948:18;;;4941:34;;;19939:169:10::1;::::0;4852:2:12;4837:18;19939:169:10::1;;;;;;;18835:1280;;2398:20:8::0;1713:1;2924:7;:21;2744:208;2398:20;18729:1386:10;;:::o;23949:1067::-;24140:25;24276:8;24258:15;:26;24254:48;;;24293:9;;;;;;;;;;;;;;24254:48;24382:17;24407:67;24432:8;24467:4;24407:12;:67::i;:::-;24381:93;;;;24500:12;24488:9;:24;24484:134;;;24535:72;;;;;;;;7576:25:12;;;7617:18;;;7610:34;;;7549:18;;24535:72:10;7402:248:12;24484:134:10;24687:71;:34;24694:9;24687:34;24722:10;24742:4;24749:8;24687:34;:71::i;:::-;24803:74;24822:1;24837:9;24852:2;24822:1;24862:12;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;24862:12:10;;24803:4;:74::i;:::-;24928:16;;;24942:1;24928:16;;;;;;;;;;;;;;;;;;;;-1:-1:-1;24928:16:10;24917:27;;24968:8;24954;24963:1;24954:11;;;;;;;;:::i;:::-;;;;;;:22;;;;;25000:9;24986:8;24995:1;24986:11;;;;;;;;:::i;:::-;;;;;;:23;;;;;24167:849;23949:1067;;;;;;;:::o;2029:149:9:-;2104:26;:24;:26::i;:::-;2140:31;2158:12;2140:17;:31::i;13954:92:10:-;14023:16;;;;;;;;;;;;;;2710:204:9;2765:26;:24;:26::i;:::-;2801:33;:31;:33::i;:::-;2844:29;2870:1;2844:17;:29::i;:::-;2883:24;2904:1;2883:12;:24::i;:::-;2710:204::o;6121:135:10:-;6221:7;6229:14;;6175:7;;6201:48;;6229:18;;6246:1;;6229:18;:::i;:::-;6221:27;;;;;;;;:::i;:::-;;;;;;;;;;6201:48;;;;;;;;6221:27;;;;;;;6201:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:19;:48::i;:::-;6194:55;;6121:135;:::o;14723:233::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;14832:7:10;:14;14814:15;14860:12;;;14856:39;;14874:21;14723:233;:::o;14856:39::-;14922:7;14930:14;;:18;;14947:1;;14930:18;:::i;:::-;14922:27;;;;;;;;:::i;8525:472::-;8598:16;8616:29;8647:26;8723:22;8765:1;8748:7;:14;;;;:18;;;;:::i;:::-;8723:43;;8809:20;8832:7;8840:14;8832:23;;;;;;;;:::i;:::-;;;;;;;;;;8809:46;;;;;;;;8832:23;;;;;;;8809:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;8927:63:10;;8809:46;;8927:12;:63::i;:::-;8920:70;;;;;;;;8525:472;;;:::o;25602:1004::-;25795:25;25930:8;25912:15;:26;25908:48;;;25947:9;;;;;;;;;;;;;;25908:48;26034:16;26058:37;26083:9;26058:11;:37::i;:::-;26033:62;;;;26120:11;26109:8;:22;26105:99;;;26140:64;;;;;;;;7576:25:12;;;7617:18;;;7610:34;;;7549:18;;26140:64:10;7402:248:12;26105:99:10;26275:71;:34;26282:9;26275:34;26310:10;26330:4;26337:8;26275:34;:71::i;:::-;26391:74;26410:1;26425:9;26440:2;26410:1;26450:12;;26391:74;26518:16;;;26532:1;26518:16;;;;;;;;;;;;;;;;;;;;-1:-1:-1;26518:16:10;26507:27;;26558:8;26544;26553:1;26544:11;;;;;;;;:::i;:::-;;;;;;:22;;;;;26590:9;26576:8;26585:1;26576:11;;;;;;;;:::i;:::-;;;;;;:23;;;;;25822:784;25602:1004;;;;;;;;:::o;9417:529::-;9492:16;9510:29;9541:26;9613:22;9655:1;9638:7;:14;;;;:18;;;;:::i;:::-;9613:43;;9699:20;9722:7;9730:14;9722:23;;;;;;;;:::i;:::-;;;;;;;;;;9699:46;;;;;;;;9722:23;;;;;;;9699:46;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9884:55:10;9699:46;9927:9;9884:12;:55::i;:::-;9828:111;;;;-1:-1:-1;9828:111:10;;-1:-1:-1;9417:529:10;-1:-1:-1;;;;9417:529:10:o;2048:23::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2048:23:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;16035:2457::-;16125:22;2356:21:8;:19;:21::i;:::-;16159:26:10::1;:24;:26::i;:::-;16260:15;16243:14;::::0;;;::::1;::::0;::::1;;:::i;:::-;:32;;;16239:54;;;16284:9;;;;;;;;;;;;;;16239:54;16549:3;16526:20;;::::0;::::1;:7:::0;:20:::1;:::i;:::-;:26;;;16522:59;;;16561:20;;;;;;;;;;;;;;16522:59;16662:16;::::0;;;::::1;::::0;::::1;;:::i;:::-;16641:37;;:18;::::0;;;::::1;::::0;::::1;;:::i;:::-;:37;;;16637:78;;;16687:28;;;;;;;;;;;;;;16637:78;16799:16;::::0;;;::::1;::::0;::::1;;:::i;:::-;:21;;::::0;:51;::::1;;;-1:-1:-1::0;16824:21:10::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;:26;;::::0;16799:51:::1;16795:93;;;16859:29;;;;;;;;;;;;;;16795:93;-1:-1:-1::0;16958:7:10::1;:14:::0;17057:18;;17053:175:::1;;17091:26;17120:7;17128:18;17145:1;17128:14:::0;:18:::1;:::i;:::-;17120:27;;;;;;;;:::i;:::-;;::::0;;;::::1;::::0;;;;17091:56:::1;::::0;;::::1;::::0;::::1;::::0;;17120:27:::1;::::0;;::::1;::::0;;::::1;17091:56:::0;;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;::::0;;;::::1;::::0;;;;;;;;;;::::1;::::0;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;;;::::1;::::0;::::1;::::0;;;;::::1;::::0;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;;::::1;::::0;::::1;::::0;;;;;;;::::1;;;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;;::::1;::::0;;;;;;::::1;;::::0;;;;::::1;::::0;;;::::1;;;::::0;::::1;::::0;;;;;;-1:-1:-1;17161:56:10::1;;17193:24;;;;;;;;;;;;;;17161:56;17077:151;17053:175;17294:551;::::0;;::::1;::::0;::::1;::::0;;;17268:7:::1;::::0;17294:551;17333:20:::1;;::::0;::::1;:7:::0;:20:::1;:::i;:::-;17294:551;;::::0;;::::1;::::0;;::::1;::::0;17383:20:::1;::::0;;::::1;:7:::0;:20:::1;:::i;:::-;17294:551;;;;;;17438:1;17294:551;;;;;;17475:1;17294:551;;;;;;17512:1;17294:551;;;;;;17542:7;:18;;;;;;;;;;:::i;:::-;17294:551;;::::0;;::::1;;17588:16;::::0;;;::::1;::::0;::::1;;:::i;:::-;17294:551;;::::0;;::::1;;17634:18;::::0;;;::::1;::::0;::::1;;:::i;:::-;17294:551;;::::0;;::::1;;17685:21;::::0;;;::::1;::::0;::::1;;:::i;:::-;17294:551;;::::0;;::::1;17744:15;17294:551;;::::0;::::1;::::0;;;17786:14:::1;::::0;;;::::1;::::0;::::1;;:::i;:::-;17294:551;::::0;;::::1;::::0;;17826:4:::1;17294:551;::::0;;::::1;::::0;;;17268:587;;;;::::1;::::0;;-1:-1:-1;17268:587:10;;;;;;;;;;;::::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;::::1;;;::::0;;::::1;::::0;;::::1;::::0;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;;::::0;;::::1;::::0;;;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;;;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;;;::::1;::::0;;::::1;::::0;;::::1;::::0;;;::::1;::::0;::::1;::::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;;::::1;::::0;::::1;::::0;::::1;::::0;;::::1;::::0;;;::::1;::::0;;;;;;;;;::::1;::::0;;;::::1;;::::0;::::1;::::0;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;17871:331:::1;::::0;17915:14;;17957:20:::1;::::0;;::::1;::::0;::::1;:::i;:::-;18003:18;::::0;;;::::1;::::0;::::1;;:::i;:::-;18045:16;::::0;;;::::1;::::0;::::1;;:::i;:::-;18087:18;::::0;;;::::1;::::0;::::1;;:::i;:::-;18134:21;::::0;;;::::1;::::0;::::1;;:::i;:::-;18177:14;::::0;;;::::1;::::0;::::1;;:::i;:::-;17871:331;::::0;;18954:25:12;;;18998:34;19068:15;;;19063:2;19048:18;;19041:43;19120:15;;;19100:18;;;19093:43;19172:15;;;;19167:2;19152:18;;19145:43;19207:18;19262:15;;;19256:3;19241:19;;19234:44;19315:15;;;19309:3;19294:19;;19287:44;19380:10;19368:23;;;19362:3;19347:19;;19340:52;17871:331:10;;;;;18941:3:12;17871:331:10;;::::1;18297:46;18336:4;18297:27;:46::i;:::-;18401:84;18437:10;18457:4;18464:20;;::::0;::::1;:7:::0;:20:::1;:::i;:::-;18401:35;18408:10;18401:35;::::0;:84;;::::1;;:35;:84::i;:::-;2398:20:8::0;1713:1;2924:7;:21;2744:208;2398:20;16035:2457:10;;;:::o;5431:581::-;5504:14;5557;5615:7;:19;;;5597:37;;:15;:37;;;;:::i;:::-;5575:7;:18;;;:60;;;;;;:::i;:::-;5557:79;;5764:6;5744:7;:17;;;:26;;;5740:155;;;-1:-1:-1;;5802:16:10;;;5793:25;;;5431:581::o;5740:155::-;5878:6;5858:7;:17;;;:26;;;;;;:::i;:::-;5849:35;;5962:7;:16;;;5953:25;;:6;:25;5949:56;;;5989:7;:16;;;5980:25;;;;5949:56;5520:492;5431:581;;;:::o;12588:259::-;12666:17;12710:9;12699:20;;:7;:20;;;12695:49;;12728:16;;;;;;;;;;;;;;12695:49;12772:68;12797:8;12832:5;12772:12;:68::i;2326:136:9:-;2387:33;:31;:33::i;:::-;2430:25;:23;:25::i;2431:307:8:-;1755:1;2558:7;;:18;2554:86;;2599:30;;;;;;;;;;;;;;2554:86;1755:1;2714:7;:17;2431:307::o;1303:160:5:-;1412:43;;1427:14;19595:55:12;;;1412:43:5;;;19577:74:12;19667:18;;;19660:34;;;1385:71:5;;1405:5;;1427:14;;;;;19550:18:12;;1412:43:5;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1385:19;:71::i;:::-;1303:160;;;:::o;10341:1397:10:-;10450:16;10468:29;10499:26;10563:7;:14;;;10558:46;;10586:18;;;;;;;;;;;;;;10558:46;10637:7;:14;;;10618:33;;:15;:33;10614:62;;10660:16;;;;;;;;;;;;;;10614:62;10702:7;:18;;;10690:30;;:9;:30;10686:76;;;10729:33;;;;;;;;;;;;;;10686:76;10866:25;10894:41;10925:7;10894:19;:41::i;:::-;10866:69;;1988:4;11394:7;:21;;;11386:30;;11374:9;:42;;;;:::i;:::-;11373:56;;;;:::i;:::-;11361:68;;1988:4;11361:68;:::i;:::-;11315:29;11327:17;11315:9;:29;:::i;:::-;11314:116;;;;:::i;:::-;11291:139;;1988:4;11594:8;11570:7;:21;;;:32;;;;;;:::i;:::-;11569:46;;;;:::i;:::-;11545:70;-1:-1:-1;11667:25:10;11545:70;11667:1;:25;:::i;:::-;11646:47;;:17;:47;:::i;:::-;11625:68;;10527:1211;10341:1397;;;;;:::o;28460:176::-;28520:14;28559:17;28550:26;;28546:49;;;28585:10;;;;;;;;;;;;;;28546:49;-1:-1:-1;28622:6:10;28460:176::o;5353:97:9:-;5413:30;5432:10;5413:18;:30::i;27548:873:10:-;27717:39;;;;;27750:4;27717:39;;;4007:74:12;27699:15:10;;27717:24;;;;;;3980:18:12;;27717:39:10;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;27699:57;;27848:13;27838:7;:23;27834:581;;;27877:14;27894:23;27904:13;27894:7;:23;:::i;:::-;27877:40;;27986:7;27982:361;;;28037:7;28045:14;;28013:21;;28037:7;28045:18;;28062:1;;28045:18;:::i;:::-;28037:27;;;;;;;;:::i;:::-;;;;;;;;;;;28013:51;;28096:9;28086:19;;:6;:19;;;28082:247;;28155:19;28167:6;28155:11;:19::i;:::-;28129:22;;;:45;;:22;;:45;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;28082:247;;;28291:19;28303:6;28291:11;:19::i;:::-;28264:23;;;:46;;:23;;:46;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;28082:247;27995:348;27982:361;28357:47;:27;;;28385:10;28397:6;28357:27;:47::i;:::-;27863:552;27642:779;27548:873;;;:::o;26985:251::-;27054:82;27088:9;27114:1;27126:7;27054:23;:82::i;:::-;27146:83;27180:10;27207:1;27219:7;27146:23;:83::i;1702:188:5:-;1829:53;;1844:18;20188:15:12;;;1829:53:5;;;20170:34:12;20240:15;;;20220:18;;;20213:43;20272:18;;;20265:34;;;1802:81:5;;1822:5;;1844:18;;;;;20082::12;;1829:53:5;19907:398:12;3386:181:9;3454:22;:37;;;;;;;;;;;;;;3530:15;;3506:54;;3454:37;;3530:15;;3506:54;;-1:-1:-1;;3506:54:9;3386:181;:::o;6546:111::-;6613:37;6639:10;6613:25;:37::i;4072:165::-;4160:15;;4140:50;;;;;;;4160:15;;4140:50;;4160:15;;4140:50;4200:15;:30;;;;;;;;;;;;;;;4072:165::o;3733:130::-;3787:22;:35;;;;;;3832:24;3845:10;3832:12;:24::i;4059:629:5:-;4478:23;4504:33;:27;;;4532:4;4504:27;:33::i;:::-;4478:59;;4551:10;:17;4572:1;4551:22;;:57;;;;;4589:10;4578:30;;;;;;;;;;;;:::i;:::-;4577:31;4551:57;4547:135;;;4631:40;;;;;4037:42:12;4025:55;;4631:40:5;;;4007:74:12;3980:18;;4631:40:5;3861:226:12;5005:159:9;4805:15;;;4793:27;;;4805:15;;4793:27;5075:82;;5131:15;;5110:47;;;;;5131:15;;;;5110:47;;;20795:34:12;20865:15;;;20845:18;;;20838:43;20707:18;;5110:47:9;20560:327:12;6171:187:9;5876:22;;;5864:34;;;5876:22;;5864:34;6248:103;;6318:22;;6290:61;;;;;6318:22;;;;6290:61;;;20795:34:12;20865:15;;;20845:18;;;20838:43;20707:18;;6290:61:9;20560:327:12;2705:151:6;2780:12;2811:38;2833:6;2841:4;2847:1;2811:21;:38::i;:::-;2804:45;;2705:151;;;;;:::o;3180:392::-;3279:12;3331:5;3307:21;:29;3303:108;;;3359:41;;;;;3394:4;3359:41;;;4007:74:12;3980:18;;3359:41:6;3861:226:12;3303:108:6;3421:12;3435:23;3462:6;:11;;3481:5;3488:4;3462:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3420:73;;;;3510:55;3537:6;3545:7;3554:10;3510:26;:55::i;:::-;3503:62;;;;3180:392;;;;;;:::o;4625:582::-;4769:12;4798:7;4793:408;;4821:19;4829:10;4821:7;:19::i;:::-;4793:408;;;5045:17;;:22;:49;;;;-1:-1:-1;5071:18:6;;;;:23;5045:49;5041:119;;;5121:24;;;;;4037:42:12;4025:55;;5121:24:6;;;4007:74:12;3980:18;;5121:24:6;3861:226:12;5041:119:6;-1:-1:-1;5180:10:6;5173:17;;5743:516;5874:17;;:21;5870:383;;6102:10;6096:17;6158:15;6145:10;6141:2;6137:19;6130:44;5870:383;6225:17;;;;;;;;;;;;;;14:196:12;82:20;;142:42;131:54;;121:65;;111:93;;200:1;197;190:12;215:184;267:77;264:1;257:88;364:4;361:1;354:15;388:4;385:1;378:15;404:252;476:2;470:9;518:3;506:16;;552:18;537:34;;573:22;;;534:62;531:88;;;599:18;;:::i;:::-;635:2;628:22;404:252;:::o;661:334::-;732:2;726:9;788:2;778:13;;793:66;774:86;762:99;;891:18;876:34;;912:22;;;873:62;870:88;;;938:18;;:::i;:::-;974:2;967:22;661:334;;-1:-1:-1;661:334:12:o;1000:1033::-;1095:6;1103;1111;1119;1172:3;1160:9;1151:7;1147:23;1143:33;1140:53;;;1189:1;1186;1179:12;1140:53;1225:9;1212:23;1202:33;;1254:2;1303;1292:9;1288:18;1275:32;1265:42;;1326:38;1360:2;1349:9;1345:18;1326:38;:::i;:::-;1316:48;;1415:2;1404:9;1400:18;1387:32;1438:18;1479:2;1471:6;1468:14;1465:34;;;1495:1;1492;1485:12;1465:34;1533:6;1522:9;1518:22;1508:32;;1578:7;1571:4;1567:2;1563:13;1559:27;1549:55;;1600:1;1597;1590:12;1549:55;1636:2;1623:16;1658:2;1654;1651:10;1648:36;;;1664:18;;:::i;:::-;1706:112;1814:2;1745:66;1738:4;1734:2;1730:13;1726:86;1722:95;1706:112;:::i;:::-;1693:125;;1841:2;1834:5;1827:17;1881:7;1876:2;1871;1867;1863:11;1859:20;1856:33;1853:53;;;1902:1;1899;1892:12;1853:53;1957:2;1952;1948;1944:11;1939:2;1932:5;1928:14;1915:45;2001:1;1996:2;1991;1984:5;1980:14;1976:23;1969:34;;2022:5;2012:15;;;;;1000:1033;;;;;;;:::o;2038:316::-;2115:6;2123;2131;2184:2;2172:9;2163:7;2159:23;2155:32;2152:52;;;2200:1;2197;2190:12;2152:52;-1:-1:-1;;2223:23:12;;;2293:2;2278:18;;2265:32;;-1:-1:-1;2344:2:12;2329:18;;;2316:32;;2038:316;-1:-1:-1;2038:316:12:o;2541:250::-;2626:1;2636:113;2650:6;2647:1;2644:13;2636:113;;;2726:11;;;2720:18;2707:11;;;2700:39;2672:2;2665:10;2636:113;;;-1:-1:-1;;2783:1:12;2765:16;;2758:27;2541:250::o;2796:330::-;2838:3;2876:5;2870:12;2903:6;2898:3;2891:19;2919:76;2988:6;2981:4;2976:3;2972:14;2965:4;2958:5;2954:16;2919:76;:::i;:::-;3040:2;3028:15;3045:66;3024:88;3015:98;;;;3115:4;3011:109;;2796:330;-1:-1:-1;;2796:330:12:o;3131:220::-;3280:2;3269:9;3262:21;3243:4;3300:45;3341:2;3330:9;3326:18;3318:6;3300:45;:::i;4092:118::-;4178:5;4171:13;4164:21;4157:5;4154:32;4144:60;;4200:1;4197;4190:12;4215:128;4280:20;;4309:28;4280:20;4309:28;:::i;4348:309::-;4413:6;4421;4474:2;4462:9;4453:7;4449:23;4445:32;4442:52;;;4490:1;4487;4480:12;4442:52;4526:9;4513:23;4503:33;;4586:2;4575:9;4571:18;4558:32;4599:28;4621:5;4599:28;:::i;:::-;4646:5;4636:15;;;4348:309;;;;;:::o;4986:254::-;5054:6;5062;5115:2;5103:9;5094:7;5090:23;5086:32;5083:52;;;5131:1;5128;5121:12;5083:52;5167:9;5154:23;5144:33;;5196:38;5230:2;5219:9;5215:18;5196:38;:::i;:::-;5186:48;;4986:254;;;;;:::o;5245:180::-;5304:6;5357:2;5345:9;5336:7;5332:23;5328:32;5325:52;;;5373:1;5370;5363:12;5325:52;-1:-1:-1;5396:23:12;;5245:180;-1:-1:-1;5245:180:12:o;5757:1640::-;5971:13;;5507:34;5496:46;5484:59;;5939:3;5924:19;;6043:4;6035:6;6031:17;6025:24;6058:54;6106:4;6095:9;6091:20;6077:12;5507:34;5496:46;5484:59;;5430:119;6058:54;;6161:4;6153:6;6149:17;6143:24;6176:56;6226:4;6215:9;6211:20;6195:14;5507:34;5496:46;5484:59;;5430:119;6176:56;;6281:4;6273:6;6269:17;6263:24;6296:56;6346:4;6335:9;6331:20;6315:14;5507:34;5496:46;5484:59;;5430:119;6296:56;;6401:4;6393:6;6389:17;6383:24;6416:56;6466:4;6455:9;6451:20;6435:14;5507:34;5496:46;5484:59;;5430:119;6416:56;;6521:4;6513:6;6509:17;6503:24;6536:56;6586:4;6575:9;6571:20;6555:14;5507:34;5496:46;5484:59;;5430:119;6536:56;;6641:4;6633:6;6629:17;6623:24;6656:56;6706:4;6695:9;6691:20;6675:14;5507:34;5496:46;5484:59;;5430:119;6656:56;;6761:4;6753:6;6749:17;6743:24;6776:55;6825:4;6814:9;6810:20;6794:14;5630:18;5619:30;5607:43;;5554:102;6776:55;-1:-1:-1;6850:6:12;6893:15;;;6887:22;5630:18;5619:30;6952:18;;;5607:43;6990:6;7033:15;;;7027:22;3432:10;3421:22;;;7092:18;;;3409:35;;;;7130:6;7173:15;;;7167:22;3421;;;7232:18;;;3409:35;7270:6;7314:15;;;7308:22;5731:13;5724:21;7372:18;;;;5712:34;;;;5757:1640;:::o;7655:1232::-;7775:6;7783;7791;7799;7807;7860:3;7848:9;7839:7;7835:23;7831:33;7828:53;;;7877:1;7874;7867:12;7828:53;7913:9;7900:23;7890:33;;7942:2;7991;7980:9;7976:18;7963:32;7953:42;;8046:2;8035:9;8031:18;8018:32;8069:18;8110:2;8102:6;8099:14;8096:34;;;8126:1;8123;8116:12;8096:34;8164:6;8153:9;8149:22;8139:32;;8209:7;8202:4;8198:2;8194:13;8190:27;8180:55;;8231:1;8228;8221:12;8180:55;8267:2;8254:16;8289:2;8285;8282:10;8279:36;;;8295:18;;:::i;:::-;8341:2;8338:1;8334:10;8324:20;;8364:28;8388:2;8384;8380:11;8364:28;:::i;:::-;8426:15;;;8496:11;;;8492:20;;;8457:12;;;;8524:19;;;8521:39;;;8556:1;8553;8546:12;8521:39;8580:11;;;;8600:148;8616:6;8611:3;8608:15;8600:148;;;8682:23;8701:3;8682:23;:::i;:::-;8670:36;;8633:12;;;;8726;;;;8600:148;;;8767:5;8757:15;;;;;;;;8791:38;8825:2;8814:9;8810:18;8791:38;:::i;:::-;7655:1232;;;;-1:-1:-1;7655:1232:12;;8876:3;8861:19;8848:33;;7655:1232;-1:-1:-1;;7655:1232:12:o;8892:632::-;9063:2;9115:21;;;9185:13;;9088:18;;;9207:22;;;9034:4;;9063:2;9286:15;;;;9260:2;9245:18;;;9034:4;9329:169;9343:6;9340:1;9337:13;9329:169;;;9404:13;;9392:26;;9473:15;;;;9438:12;;;;9365:1;9358:9;9329:169;;;-1:-1:-1;9515:3:12;;8892:632;-1:-1:-1;;;;;;8892:632:12:o;9529:186::-;9588:6;9641:2;9629:9;9620:7;9616:23;9612:32;9609:52;;;9657:1;9654;9647:12;9609:52;9680:29;9699:9;9680:29;:::i;9720:260::-;9788:6;9796;9849:2;9837:9;9828:7;9824:23;9820:32;9817:52;;;9865:1;9862;9855:12;9817:52;9888:29;9907:9;9888:29;:::i;:::-;9878:39;;9936:38;9970:2;9959:9;9955:18;9936:38;:::i;9985:895::-;10107:6;10115;10123;10131;10139;10147;10200:3;10188:9;10179:7;10175:23;10171:33;10168:53;;;10217:1;10214;10207:12;10168:53;10253:9;10240:23;10230:33;;10310:2;10299:9;10295:18;10282:32;10272:42;;10365:2;10354:9;10350:18;10337:32;10388:18;10429:2;10421:6;10418:14;10415:34;;;10445:1;10442;10435:12;10415:34;10483:6;10472:9;10468:22;10458:32;;10528:7;10521:4;10517:2;10513:13;10509:27;10499:55;;10550:1;10547;10540:12;10499:55;10590:2;10577:16;10616:2;10608:6;10605:14;10602:34;;;10632:1;10629;10622:12;10602:34;10685:7;10680:2;10670:6;10667:1;10663:14;10659:2;10655:23;10651:32;10648:45;10645:65;;;10706:1;10703;10696:12;10645:65;10737:2;10733;10729:11;10719:21;;10759:6;10749:16;;;;;10784:38;10818:2;10807:9;10803:18;10784:38;:::i;:::-;10774:48;;10869:3;10858:9;10854:19;10841:33;10831:43;;9985:895;;;;;;;;:::o;12030:205::-;12127:6;12180:3;12168:9;12159:7;12155:23;12151:33;12148:53;;;12197:1;12194;12187:12;12240:188;12308:20;;12368:34;12357:46;;12347:57;;12337:85;;12418:1;12415;12408:12;12433:171;12500:20;;12560:18;12549:30;;12539:41;;12529:69;;12594:1;12591;12584:12;12609:163;12676:20;;12736:10;12725:22;;12715:33;;12705:61;;12762:1;12759;12752:12;12777:1154;12860:6;12913:3;12901:9;12892:7;12888:23;12884:33;12881:53;;;12930:1;12927;12920:12;12881:53;12956:22;;:::i;:::-;13001:29;13020:9;13001:29;:::i;:::-;12994:5;12987:44;13063:38;13097:2;13086:9;13082:18;13063:38;:::i;:::-;13058:2;13051:5;13047:14;13040:62;13134:38;13168:2;13157:9;13153:18;13134:38;:::i;:::-;13129:2;13122:5;13118:14;13111:62;13205:38;13239:2;13228:9;13224:18;13205:38;:::i;:::-;13200:2;13193:5;13189:14;13182:62;13277:39;13311:3;13300:9;13296:19;13277:39;:::i;:::-;13271:3;13264:5;13260:15;13253:64;13350:39;13384:3;13373:9;13369:19;13350:39;:::i;:::-;13344:3;13337:5;13333:15;13326:64;13423:39;13457:3;13446:9;13442:19;13423:39;:::i;:::-;13417:3;13410:5;13406:15;13399:64;13496:38;13529:3;13518:9;13514:19;13496:38;:::i;:::-;13490:3;13483:5;13479:15;13472:63;13554:3;13589:37;13622:2;13611:9;13607:18;13589:37;:::i;:::-;13573:14;;;13566:61;13646:3;13681:37;13699:18;;;13681:37;:::i;:::-;13665:14;;;13658:61;13738:3;13773:37;13791:18;;;13773:37;:::i;:::-;13757:14;;;13750:61;13830:3;13865:35;13881:18;;;13865:35;:::i;:::-;13849:14;;;13842:59;13853:5;12777:1154;-1:-1:-1;;;12777:1154:12:o;14466:184::-;14518:77;14515:1;14508:88;14615:4;14612:1;14605:15;14639:4;14636:1;14629:15;14655:128;14722:9;;;14743:11;;;14740:37;;;14757:18;;:::i;14788:184::-;14840:77;14837:1;14830:88;14937:4;14934:1;14927:15;14961:4;14958:1;14951:15;14977:482;15220:42;15212:6;15208:55;15197:9;15190:74;15300:6;15295:2;15284:9;15280:18;15273:34;15343:6;15338:2;15327:9;15323:18;15316:34;15386:3;15381:2;15370:9;15366:18;15359:31;15171:4;15407:46;15448:3;15437:9;15433:19;15425:6;15407:46;:::i;:::-;15399:54;14977:482;-1:-1:-1;;;;;;14977:482:12:o;15464:184::-;15534:6;15587:2;15575:9;15566:7;15562:23;15558:32;15555:52;;;15603:1;15600;15593:12;15555:52;-1:-1:-1;15626:16:12;;15464:184;-1:-1:-1;15464:184:12:o;16065:200::-;16134:34;16201:10;;;16189;;;16185:27;;16224:12;;;16221:38;;;16239:18;;:::i;:::-;16221:38;16065:200;;;;:::o;17050:437::-;17129:1;17125:12;;;;17172;;;17193:61;;17247:4;17239:6;17235:17;17225:27;;17193:61;17300:2;17292:6;17289:14;17269:18;17266:38;17263:218;;17337:77;17334:1;17327:88;17438:4;17435:1;17428:15;17466:4;17463:1;17456:15;17492:168;17565:9;;;17596;;17613:15;;;17607:22;;17593:37;17583:71;;17634:18;;:::i;17665:274::-;17705:1;17731;17721:189;;17766:77;17763:1;17756:88;17867:4;17864:1;17857:15;17895:4;17892:1;17885:15;17721:189;-1:-1:-1;17924:9:12;;17665:274::o;17944:125::-;18009:9;;;18030:10;;;18027:36;;;18043:18;;:::i;18074:184::-;18132:6;18185:2;18173:9;18164:7;18160:23;18156:32;18153:52;;;18201:1;18198;18191:12;18153:52;18224:28;18242:9;18224:28;:::i;18263:186::-;18322:6;18375:2;18363:9;18354:7;18350:23;18346:32;18343:52;;;18391:1;18388;18381:12;18343:52;18414:29;18433:9;18414:29;:::i;18454:184::-;18512:6;18565:2;18553:9;18544:7;18540:23;18536:32;18533:52;;;18581:1;18578;18571:12;18533:52;18604:28;18622:9;18604:28;:::i;19705:197::-;19773:34;19827:10;;;19839;;;19823:27;;19862:11;;;19859:37;;;19876:18;;:::i;20310:245::-;20377:6;20430:2;20418:9;20409:7;20405:23;20401:32;20398:52;;;20446:1;20443;20436:12;20398:52;20478:9;20472:16;20497:28;20519:5;20497:28;:::i;20892:287::-;21021:3;21059:6;21053:13;21075:66;21134:6;21129:3;21122:4;21114:6;21110:17;21075:66;:::i;:::-;21157:16;;;;;20892:287;-1:-1:-1;;20892:287:12:o
Swarm Source
ipfs://8ec73c478f099ff03b90c422145c33e3f767a8e355a0920077a210d2face11b4
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.