false
true
0

Contract Address Details

0x01408f83FF10bBA51807418be80E6EA70a91AA4d

Contract Name
SwapLens
Creator
0x99ab03–301446 at 0x316611–a6af34
Balance
0 PLS ( )
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
25961308
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
This contract has been verified via Sourcify. View contract in Sourcify repository
Contract name:
SwapLens




Optimization enabled
true
Compiler version
v0.8.20+commit.a1b79de6




Optimization runs
200
EVM Version
paris




Verified at
2026-02-27T19:02:28.728075Z

src/SwapLens.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

/// @title ISWAP_V3 Interface
/// @notice Interface for querying the SWAP_V3 auction contract state
/// @dev This interface provides read-only access to auction schedule, daily state, and user participation data
interface ISWAP_V3 {
    // ============ Core Schedule State ============
    
    /// @notice Check if the auction schedule has been configured
    /// @return True if the schedule is set, false otherwise
    function scheduleSet() external view returns (bool);
    
    /// @notice Get the timestamp when the auction schedule starts
    /// @return Unix timestamp of schedule start
    function scheduleStart() external view returns (uint256);
    
    /// @notice Get the maximum number of auction days configured
    /// @return Total number of days the auction will run
    function auctionDaysLimit() external view returns (uint256);
    
    /// @notice Get the token address scheduled for a specific day index
    /// @param index The day index in the schedule
    /// @return The token address scheduled for that day
    function scheduledTokens(uint256 index) external view returns (address);
    
    /// @notice Get the total number of unique tokens in the schedule
    /// @return Number of scheduled tokens
    function scheduledTokensLength() external view returns (uint256);
    
    /// @notice Get the schedule index for a specific token (1-based, 0 means not scheduled)
    /// @param token The token address to query
    /// @return The 1-based index of the token in the schedule, or 0 if not scheduled
    function scheduledIndex(address token) external view returns (uint256);

    // ============ Daily State Release ============
    
    /// @notice Get the start timestamp of the current day
    /// @return Unix timestamp of current day start
    function currentDayStart() external view returns (uint256);
    
    /// @notice Get the total STATE tokens released today
    /// @return Total STATE tokens released in the current day
    function dailyStateReleased() external view returns (uint256);
    
    /// @notice Get STATE tokens released through normal swaps today
    /// @return STATE tokens released via normal swaps in the current day
    function dailyStateReleasedNormal() external view returns (uint256);
    
    /// @notice Get STATE tokens released through reverse swaps today
    /// @return STATE tokens released via reverse swaps in the current day
    function dailyStateReleasedReverse() external view returns (uint256);
    
    /// @notice Get total STATE tokens released for a specific day
    /// @param dayIndex The day index to query
    /// @return Total STATE tokens released on that day
    function stateReleasedByDayIndex(uint256 dayIndex) external view returns (uint256);
    
    /// @notice Get STATE tokens released through normal swaps for a specific day
    /// @param dayIndex The day index to query
    /// @return STATE tokens released via normal swaps on that day
    function stateReleasedNormalByDayIndex(uint256 dayIndex) external view returns (uint256);
    
    /// @notice Get STATE tokens released through reverse swaps for a specific day
    /// @param dayIndex The day index to query
    /// @return STATE tokens released via reverse swaps on that day
    function stateReleasedReverseByDayIndex(uint256 dayIndex) external view returns (uint256);

    // ============ User Participation Flags ============
    
    /// @notice Check if a user has performed a normal swap for a specific token in the current cycle
    /// @param user The user address to check
    /// @param inputToken The token address to check
    /// @return True if the user has swapped, false otherwise
    function getUserHasSwapped(address user, address inputToken) external view returns (bool);
    
    /// @notice Check if a user has performed a reverse swap for a specific token in the current cycle
    /// @param user The user address to check
    /// @param inputToken The token address to check
    /// @return True if the user has reverse swapped, false otherwise
    function getUserHasReverseSwapped(address user, address inputToken) external view returns (bool);
}

/// @title SwapLens - View-Only Utility for SWAP_V3 Auction System
/// @author State Protocol Team
/// @notice Provides comprehensive, gas-efficient read-only access to auction state and user data
/// @dev This contract is purely for data aggregation and querying - it contains no state and performs no writes
/// @dev All functions are view-only and can be called off-chain without gas costs
/// @custom:alignment Logic EXACTLY replicates SWAP_V3 time calculations and auction mechanics from AuctionUtilsLib
/// @custom:security Solidity 0.8.20 automatic overflow/underflow protection
/// @custom:design Zero-value returns for invalid inputs allow graceful degradation in frontend queries
contract SwapLens is Ownable {
    
    /// @notice Initializes SwapLens with deployer as owner and renounces ownership immediately
    /// @dev Ownership renounced since this is a pure view-only contract with no state-changing functions
    constructor() Ownable(msg.sender) {
        renounceOwnership();
    }
    
    // ============ Errors ============
    
    /// @notice Thrown when the provided SWAP_V3 address has no deployed contract
    /// @dev Prevents calls to invalid or non-existent contracts
    error InvalidContract();

    // ============ Structs ============
    
    /// @notice Comprehensive status information for the current auction day
    /// @dev Used by getTodayStatus() to return all relevant daily information
    /// @param tokenOfDay The token being auctioned today (address(0) if no active auction)
    /// @param activeWindow Whether the auction window is currently active
    /// @param isReverse Whether today is a reverse auction (every 4th appearance)
    /// @param appearanceCount How many times this token has appeared in the schedule
    /// @param secondsLeft Seconds remaining until the current day's auction ends
    struct TodayStatus {
        address tokenOfDay;
        bool activeWindow;
        bool isReverse;
        uint256 appearanceCount;
        uint256 secondsLeft;
    }

    // ============ Internal Validation & Helper Functions ============
    
    /// @notice Validates that a contract exists at the given SWAP_V3 address
    /// @dev Checks if bytecode exists at the address to prevent calls to EOAs or non-existent contracts
    /// @param s The SWAP_V3 interface instance to validate
    /// @custom:throws InvalidContract if no contract code exists at the address
    function _validate(ISWAP_V3 s) internal view {
        if (address(s).code.length == 0) revert InvalidContract();
    }

    /// @notice Checks if the auction has started
    /// @dev Auction is considered started when schedule is set AND current time >= schedule start time
    /// @param s The SWAP_V3 interface instance
    /// @return True if auction has started, false otherwise
    function _auctionStarted(ISWAP_V3 s) internal view returns (bool) {
        return s.scheduleSet() && block.timestamp >= s.scheduleStart();
    }
    
    /// @notice Calculates the current day index in the auction schedule
    /// @dev Day index is 0-based, calculated as (current_time - start_time) / 1 day
    /// @param s The SWAP_V3 interface instance
    /// @return The current day index, or 0 if auction hasn't started
    function _currentDayIndex(ISWAP_V3 s) internal view returns (uint256) {
        if (!_auctionStarted(s)) return 0;
        return (block.timestamp - s.scheduleStart()) / 1 days;
    }
    
    /// @notice Calculates the start and end timestamps for today's auction window
    /// @dev Each day is exactly 24 hours (86400 seconds)
    /// @param s The SWAP_V3 interface instance
    /// @return start Unix timestamp when today's window started
    /// @return end Unix timestamp when today's window ends
    /// @custom:timezone GMT+3 17:00 boundary encoded in scheduleStart, matches SWAP_V3 AuctionUtilsLib calculation
    function _todayWindow(ISWAP_V3 s) internal view returns (uint256 start, uint256 end) {
        uint256 d = _currentDayIndex(s);
        start = s.scheduleStart() + d * 1 days;
        end = start + 1 days;
    }
    
    /// @notice Gets the token scheduled for today and checks if the auction window is active
    /// @dev Tokens cycle through the schedule array using modulo operation
    /// @param s The SWAP_V3 interface instance
    /// @return tokenOfDay The token address for today (address(0) if no active auction)
    /// @return active True if we're currently within today's auction window
    function _getTodayToken(ISWAP_V3 s) internal view returns (address tokenOfDay, bool active) {
        if (!_auctionStarted(s)) return (address(0), false);
        uint256 d = _currentDayIndex(s);
        if (d >= s.auctionDaysLimit()) return (address(0), false);
        uint256 n = s.scheduledTokensLength();
        if (n == 0) return (address(0), false);
        tokenOfDay = s.scheduledTokens(d % n);
        (uint256 st, uint256 en) = _todayWindow(s);
        active = block.timestamp >= st && block.timestamp < en;
    }
    
    /// @notice Calculates how many times a token has appeared in the auction schedule
    /// @dev Used to determine if current appearance is a reverse auction (every 4th appearance)
    /// @dev Includes protection against division by zero
    /// @param s The SWAP_V3 interface instance
    /// @param token The token address to check
    /// @return The number of times this token has appeared (0 if not scheduled or auction not started)
    /// @custom:formula count = (currentDay - tokenIndex) / totalTokens + 1, matches AuctionUtilsLib
    function _appearanceCount(ISWAP_V3 s, address token) internal view returns (uint256) {
        if (!_auctionStarted(s)) return 0;
        uint256 idx1 = s.scheduledIndex(token);
        if (idx1 == 0) return 0; // Token not scheduled (index is 1-based)
        uint256 idx = idx1 - 1; // Convert to 0-based index (safe because idx1 > 0)
        uint256 d = _currentDayIndex(s);
        if (d < idx) return 0; // Token's first day hasn't arrived yet
        uint256 n = s.scheduledTokensLength();
        if (n == 0) return 0; // Defensive guard: prevents division by zero below
        return (d - idx) / n + 1;
    }

    /// @notice Shared computation for aggregating today's auction status
    /// @dev Used by multiple public view functions to avoid code duplication
    /// @param s The SWAP_V3 interface instance
    /// @return tokenOfDay The token being auctioned today
    /// @return active Whether the auction window is currently active
    /// @return isReverse Whether today is a reverse auction (every 4th appearance)
    /// @return appearance How many times this token has appeared
    /// @return secondsLeft Seconds remaining in today's auction window
    /// @custom:reverse Reverse auction occurs when appearance % 4 == 0 (cycles 4, 8, 12, 16, 20)
    function _statusForToday(ISWAP_V3 s)
        internal
        view
        returns (
            address tokenOfDay,
            bool active,
            bool isReverse,
            uint256 appearance,
            uint256 secondsLeft
        )
    {
        (tokenOfDay, active) = _getTodayToken(s);
        if (!active || tokenOfDay == address(0)) {
            return (address(0), false, false, 0, 0);
        }
        appearance = _appearanceCount(s, tokenOfDay);
        isReverse = (appearance > 0 && (appearance % 4 == 0));
        (, uint256 end) = _todayWindow(s);
        secondsLeft = end > block.timestamp ? end - block.timestamp : 0;
    }

    // ============ Public View Functions ============
    
    /// @notice Get comprehensive status for today's auction
    /// @dev Returns a struct with all relevant information about the current day's auction
    /// @dev Explicitly initializes all fields to zero values if no active auction
    /// @param s The SWAP_V3 contract address to query
    /// @return ts TodayStatus struct containing tokenOfDay, activeWindow, isReverse, appearanceCount, and secondsLeft
    /// @custom:throws InvalidContract if the provided address is not a deployed contract
    function getTodayStatus(ISWAP_V3 s) external view returns (TodayStatus memory ts) {
        _validate(s);
        (ts.tokenOfDay, ts.activeWindow, ts.isReverse, ts.appearanceCount, ts.secondsLeft) = _statusForToday(s);
        if (!ts.activeWindow || ts.tokenOfDay == address(0)) {
            // Explicit initialization for clarity to downstream consumers (frontends, indexers)
            ts.tokenOfDay = address(0);
            ts.activeWindow = false;
            ts.isReverse = false;
            ts.appearanceCount = 0;
            ts.secondsLeft = 0;
        }
    }

    /// @notice Get the core configuration of the auction schedule
    /// @dev Provides high-level schedule parameters without iterating through tokens
    /// @param s The SWAP_V3 contract address to query
    /// @return isSet True if the schedule has been configured
    /// @return start Unix timestamp when the schedule begins
    /// @return daysLimit Maximum number of auction days
    /// @return scheduledCount Number of unique tokens in the rotation schedule
    /// @custom:throws InvalidContract if the provided address is not a deployed contract
    function getScheduleConfig(ISWAP_V3 s)
        external
        view
        returns (bool isSet, uint256 start, uint256 daysLimit, uint256 scheduledCount)
    {
        _validate(s);
        isSet = s.scheduleSet();
        start = s.scheduleStart();
        daysLimit = s.auctionDaysLimit();
        scheduledCount = s.scheduledTokensLength();
    }

    /// @notice Get the complete list of all scheduled tokens
    /// @dev Returns all tokens in the rotation schedule order
    /// @dev WARNING: Can be gas-intensive for large schedules. Use getScheduledTokensPaginated for large lists
    /// @param s The SWAP_V3 contract address to query
    /// @return list Array of all scheduled token addresses in order
    /// @custom:throws InvalidContract if the provided address is not a deployed contract
    /// @custom:gas View-only function (zero gas for off-chain calls), paginated alternative available
    /// @custom:limit Max 50 tokens enforced in SWAP_V3 deployment
    function getScheduledTokens(ISWAP_V3 s) external view returns (address[] memory list) {
        _validate(s);
        uint256 n = s.scheduledTokensLength();
        list = new address[](n);
        for (uint256 i = 0; i < n; i++) {
            list[i] = s.scheduledTokens(i);
        }
    }

    /// @notice Get a paginated subset of scheduled tokens
    /// @dev Use this for large schedules to avoid gas limits. More efficient for frontend pagination
    /// @param s The SWAP_V3 contract address to query
    /// @param start The starting index (0-based) for pagination
    /// @param limit The maximum number of tokens to return
    /// @return list Array of token addresses from start to start+limit (or end of list)
    /// @custom:throws InvalidContract if the provided address is not a deployed contract
    function getScheduledTokensPaginated(ISWAP_V3 s, uint256 start, uint256 limit)
        external
        view
        returns (address[] memory list)
    {
        _validate(s);
        uint256 n = s.scheduledTokensLength();
        if (start >= n) return new address[](0);
        uint256 end = start + limit;
        if (end > n) end = n;
        uint256 size = end - start;
        list = new address[](size);
        for (uint256 i = 0; i < size; i++) {
            list[i] = s.scheduledTokens(start + i);
        }
    }

    /// @notice Get detailed schedule information for a specific token
    /// @dev Provides the token's position in schedule and appearance history
    /// @param s The SWAP_V3 contract address to query
    /// @param token The token address to look up
    /// @return isScheduled True if the token is in the rotation schedule
    /// @return index The 1-based schedule index (0 if not scheduled)
    /// @return appearancesToDate Number of times this token has appeared so far
    /// @return isReverseToday True if the current/next appearance is a reverse auction (every 4th)
    /// @return currentDay The current day index in the auction
    /// @custom:throws InvalidContract if the provided address is not a deployed contract
    function getTokenScheduleInfo(ISWAP_V3 s, address token)
        external
        view
        returns (bool isScheduled, uint256 index, uint256 appearancesToDate, bool isReverseToday, uint256 currentDay)
    {
        _validate(s);
        index = s.scheduledIndex(token);
        isScheduled = index != 0;
        appearancesToDate = _appearanceCount(s, token);
        isReverseToday = appearancesToDate > 0 && (appearancesToDate % 4 == 0);
        currentDay = _auctionStarted(s) ? _currentDayIndex(s) : 0;
    }

    /// @notice Get the breakdown of STATE tokens released in the current day
    /// @dev Separates normal swaps from reverse swaps for analytics
    /// @param s The SWAP_V3 contract address to query
    /// @return dayIndex The current day index
    /// @return total Total STATE tokens released today (normal + reverse)
    /// @return normal STATE tokens released through normal swaps today
    /// @return reverse STATE tokens released through reverse swaps today
    /// @custom:throws InvalidContract if the provided address is not a deployed contract
    function getDailyStateReleaseBreakdown(ISWAP_V3 s)
        external
        view
        returns (uint256 dayIndex, uint256 total, uint256 normal, uint256 reverse)
    {
        _validate(s);
        dayIndex = s.currentDayStart() / 1 days;
        total = s.dailyStateReleased();
        normal = s.dailyStateReleasedNormal();
        reverse = s.dailyStateReleasedReverse();
    }

    /// @notice Get STATE token release data for a specific historical day
    /// @dev Allows querying past days for historical analysis and charts
    /// @param s The SWAP_V3 contract address to query
    /// @param dayIndex The day index to query (0 = first day)
    /// @return total Total STATE tokens released on that day
    /// @return normal STATE tokens released through normal swaps on that day
    /// @return reverse STATE tokens released through reverse swaps on that day
    /// @custom:throws InvalidContract if the provided address is not a deployed contract
    /// @custom:behavior Returns zero for invalid/future days rather than reverting (enables batch queries)
    function getStateReleasedByDay(ISWAP_V3 s, uint256 dayIndex)
        external
        view
        returns (uint256 total, uint256 normal, uint256 reverse)
    {
        _validate(s);
        total = s.stateReleasedByDayIndex(dayIndex);
        normal = s.stateReleasedNormalByDayIndex(dayIndex);
        reverse = s.stateReleasedReverseByDayIndex(dayIndex);
    }

    /// @notice Get a user's swap participation status for a specific token
    /// @dev Tracks whether user has performed normal/reverse swaps in the current cycle
    /// @param s The SWAP_V3 contract address to query
    /// @param user The user address to check
    /// @param inputToken The token to check swap status for
    /// @return hasSwapped True if user has performed a normal swap in this cycle
    /// @return hasReverseSwapped True if user has performed a reverse swap in this cycle
    /// @return cycle The current appearance count (cycle number) for this token
    /// @custom:throws InvalidContract if the provided address is not a deployed contract
    function getUserSwapStatus(ISWAP_V3 s, address user, address inputToken)
        external
        view
        returns (bool hasSwapped, bool hasReverseSwapped, uint256 cycle)
    {
        _validate(s);
        hasSwapped = s.getUserHasSwapped(user, inputToken);
        hasReverseSwapped = s.getUserHasReverseSwapped(user, inputToken);
        cycle = _appearanceCount(s, inputToken);
    }

    /// @notice Get a comprehensive dashboard view combining today's status with user participation
    /// @dev Optimized single-call function for frontend dashboards - reduces RPC calls
    /// @param s The SWAP_V3 contract address to query
    /// @param user The user address to check participation for
    /// @return tokenOfDay The token being auctioned today
    /// @return active Whether the auction window is currently active
    /// @return isReverse Whether today is a reverse auction
    /// @return secondsLeft Seconds remaining in today's auction window
    /// @return appearance Number of times today's token has appeared
    /// @return userHasSwapped Whether the user has performed a normal swap today
    /// @return userHasReverseSwapped Whether the user has performed a reverse swap today
    /// @custom:throws InvalidContract if the provided address is not a deployed contract
    function getTodayDashboard(ISWAP_V3 s, address user)
        external
        view
        returns (address tokenOfDay, bool active, bool isReverse, uint256 secondsLeft, uint256 appearance, bool userHasSwapped, bool userHasReverseSwapped)
    {
        _validate(s);
        (tokenOfDay, active, isReverse, appearance, secondsLeft) = _statusForToday(s);
        if (!active || tokenOfDay == address(0)) {
            return (address(0), false, false, 0, 0, false, false);
        }
        userHasSwapped = s.getUserHasSwapped(user, tokenOfDay);
        userHasReverseSwapped = s.getUserHasReverseSwapped(user, tokenOfDay);
    }
}
        

/Context.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
          

/Ownable.sol

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)

pragma solidity ^0.8.20;

import {Context} from "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * The initial owner is set to the address provided by the deployer. This can
 * later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}
          

Compiler Settings

{"viaIR":true,"remappings":[":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",":forge-std/=lib/forge-std/src/",":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",":openzeppelin-contracts/=lib/openzeppelin-contracts/"],"optimizer":{"runs":200,"enabled":true},"metadata":{"bytecodeHash":"ipfs"},"libraries":{},"evmVersion":"paris","compilationTarget":{"src/SwapLens.sol":"SwapLens"}}
              

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"error","name":"InvalidContract","inputs":[]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"type":"address","name":"owner","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"dayIndex","internalType":"uint256"},{"type":"uint256","name":"total","internalType":"uint256"},{"type":"uint256","name":"normal","internalType":"uint256"},{"type":"uint256","name":"reverse","internalType":"uint256"}],"name":"getDailyStateReleaseBreakdown","inputs":[{"type":"address","name":"s","internalType":"contract ISWAP_V3"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"isSet","internalType":"bool"},{"type":"uint256","name":"start","internalType":"uint256"},{"type":"uint256","name":"daysLimit","internalType":"uint256"},{"type":"uint256","name":"scheduledCount","internalType":"uint256"}],"name":"getScheduleConfig","inputs":[{"type":"address","name":"s","internalType":"contract ISWAP_V3"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"list","internalType":"address[]"}],"name":"getScheduledTokens","inputs":[{"type":"address","name":"s","internalType":"contract ISWAP_V3"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address[]","name":"list","internalType":"address[]"}],"name":"getScheduledTokensPaginated","inputs":[{"type":"address","name":"s","internalType":"contract ISWAP_V3"},{"type":"uint256","name":"start","internalType":"uint256"},{"type":"uint256","name":"limit","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"total","internalType":"uint256"},{"type":"uint256","name":"normal","internalType":"uint256"},{"type":"uint256","name":"reverse","internalType":"uint256"}],"name":"getStateReleasedByDay","inputs":[{"type":"address","name":"s","internalType":"contract ISWAP_V3"},{"type":"uint256","name":"dayIndex","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"tokenOfDay","internalType":"address"},{"type":"bool","name":"active","internalType":"bool"},{"type":"bool","name":"isReverse","internalType":"bool"},{"type":"uint256","name":"secondsLeft","internalType":"uint256"},{"type":"uint256","name":"appearance","internalType":"uint256"},{"type":"bool","name":"userHasSwapped","internalType":"bool"},{"type":"bool","name":"userHasReverseSwapped","internalType":"bool"}],"name":"getTodayDashboard","inputs":[{"type":"address","name":"s","internalType":"contract ISWAP_V3"},{"type":"address","name":"user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"ts","internalType":"struct SwapLens.TodayStatus","components":[{"type":"address","name":"tokenOfDay","internalType":"address"},{"type":"bool","name":"activeWindow","internalType":"bool"},{"type":"bool","name":"isReverse","internalType":"bool"},{"type":"uint256","name":"appearanceCount","internalType":"uint256"},{"type":"uint256","name":"secondsLeft","internalType":"uint256"}]}],"name":"getTodayStatus","inputs":[{"type":"address","name":"s","internalType":"contract ISWAP_V3"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"isScheduled","internalType":"bool"},{"type":"uint256","name":"index","internalType":"uint256"},{"type":"uint256","name":"appearancesToDate","internalType":"uint256"},{"type":"bool","name":"isReverseToday","internalType":"bool"},{"type":"uint256","name":"currentDay","internalType":"uint256"}],"name":"getTokenScheduleInfo","inputs":[{"type":"address","name":"s","internalType":"contract ISWAP_V3"},{"type":"address","name":"token","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"hasSwapped","internalType":"bool"},{"type":"bool","name":"hasReverseSwapped","internalType":"bool"},{"type":"uint256","name":"cycle","internalType":"uint256"}],"name":"getUserSwapStatus","inputs":[{"type":"address","name":"s","internalType":"contract ISWAP_V3"},{"type":"address","name":"user","internalType":"address"},{"type":"address","name":"inputToken","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]}]
              

Contract Creation Code

0x6080806040523461006257600080547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090336001600160a01b038216838580a36001600160a01b031990811633918216178355908280a361159690816100688239f35b600080fdfe60406080815260048036101561001457600080fd5b600091823560e01c80631d0d856d14610b425780633c4d4d5014610b0857806351bd7b8e14610a1a5780636f39eb1114610892578063715018a6146108355780637acbbdae146106c65780638138e5ac1461055f5780638da5cb5b146105335780639330edd5146103725780639a68c81914610265578063f2fde38b146101de5763f3df535f146100a457600080fd5b346101da576020806003193601126101d6576100be610baa565b6100c781610c83565b825163749c49f760e11b8152916001600160a01b039182169080848781855afa9384156101cc578794610199575b506100ff84611247565b95875b85811061011a578651806101168a82610bdb565b0390f35b8651630e2c6b6160e41b81528281018290528381602481885afa90811561018f579061015d92918b91610162575b5086610154838c611288565b91169052611279565b610102565b6101829150853d8711610188575b61017a8183610c4b565b810190610f61565b38610148565b503d610170565b88513d8c823e3d90fd5b9080945081813d83116101c5575b6101b18183610c4b565b810103126101c1575192386100f5565b8680fd5b503d6101a7565b85513d89823e3d90fd5b8380fd5b8280fd5b5090346101da5760203660031901126101da576101f9610baa565b90610202610c1f565b6001600160a01b0391821692831561024f57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b51631e4fbdf760e01b8152908101849052602490fd5b50346101da57806003193601126101da57602491610281610baa565b90602061028c610bc5565b9161029684610c83565b845163a01986a760e01b81526001600160a01b0384811692820192909252958691829086165afa93841561036857859461032f575b50936102d960a09583611103565b908115159283610323575b6102ed81610ea8565b1561031c576102fc9150610e04565b925b80519480151586526020860152840152151560608301526080820152f35b50926102fe565b600383161593506102e4565b9093506020813d8211610360575b8161034a60209383610c4b565b8101031261035c5751926102d96102cb565b8480fd5b3d915061033d565b83513d87823e3d90fd5b5090346101da57602091826003193601126101d65761038f610baa565b61039881610c83565b8151635a4d30cd60e01b8152936001600160a01b0391909116919080858581865afa9485156105295786956104f6575b50815163588241c960e11b81529080828681875afa9182156104805787926104c7575b5082516304dce4e160e41b81529381858781845afa9485156104bd57889561048a575b5081908451968780926302c8de7960e11b82525afa94851561048057879561044d575b5060809650620151808351960486528501528301526060820152f35b9080955081813d8311610479575b6104658183610c4b565b810103126101c15760809650519338610431565b503d61045b565b83513d89823e3d90fd5b9094508181813d83116104b6575b6104a28183610c4b565b810103126104b25751938161040e565b8780fd5b503d610498565b84513d8a823e3d90fd5b9080925081813d83116104ef575b6104df8183610c4b565b810103126101c1575190386103eb565b503d6104d5565b9080955081813d8311610522575b61050e8183610c4b565b8101031261051e575193386103c8565b8580fd5b503d610504565b82513d88823e3d90fd5b83823461055b578160031936011261055b57905490516001600160a01b039091168152602090f35b5080fd5b50346101da5760603660031901126101da57610579610baa565b90610582610bc5565b6044356001600160a01b0380821682036101c15761059f85610c83565b8351634e79043360e11b81526001600160a01b03808516888301908152908416602082810191909152919691949192831691908590889081906040010381855afa9687156106bc578997610693575b50855163183e35db60e21b81526001600160a01b039182169881019889529084166020890152959684918791829081906040015b03915afa9485156106895760609795610654575b509061064191611103565b9282519415158552151590840152820152f35b6106419291955061067a90843d8611610682575b6106728183610c4b565b810190610e90565b949091610636565b503d610668565b84513d89823e3d90fd5b61062297509184916106b28794853d8711610682576106728183610c4b565b98509150916105ee565b86513d8b823e3d90fd5b5090346101da57816003193601126101da576106e0610baa565b91602435926106ee81610c83565b8151631a13e1e760e21b8152808401859052936001600160a01b0391909116929060208086602481885afa958615610689578796610806575b508351631ac57d5560e01b8152838101839052918183602481895afa9283156107fc5788936107ca575b50602482939486519788938492630d72ffff60e21b84528301525afa9384156107c057869461078d575b50606095508251948552840152820152f35b9080945081813d83116107b9575b6107a58183610c4b565b8101031261051e576060955051923861077b565b503d61079b565b83513d88823e3d90fd5b9180935082813d83116107f5575b6107e28183610c4b565b810103126104b257905191906024610751565b503d6107d8565b85513d8a823e3d90fd5b9080965081813d831161082e575b61081e8183610c4b565b810103126101c157519438610727565b503d610814565b833461088f578060031936011261088f5761084e610c1f565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b5090346101da57602091826003193601126101d6576108af610baa565b6108b881610c83565b81516367cbdec360e01b8152936001600160a01b0391909116919080858581865afa9485156105295786956109fb575b5081516346706c2960e01b81529080828681875afa9182156104805787926109cc575b50825163629f0dc960e11b81529381858781845afa9485156104bd57889561099d575b50819084519687809263749c49f760e11b82525afa94851561048057879561096a575b5060809650825195151586528501528301526060820152f35b9080955081813d8311610996575b6109828183610c4b565b810103126101c15760809650519338610951565b503d610978565b9094508181813d83116109c5575b6109b58183610c4b565b810103126104b25751938161092e565b503d6109ab565b9080925081813d83116109f4575b6109e48183610c4b565b810103126101c15751903861090b565b503d6109da565b81610a139296503d8711610682576106728183610c4b565b93386108e8565b50823461088f57602036600319011261088f57610a35610baa565b9082519260a0840184811067ffffffffffffffff821117610af55760a09550815281845260208401828152818501908382526060860193808552610a886080880196828852610a8381610c83565b610cc9565b8a5288521515855215801580855260001960018c1b01928316808b5292939290610aec575b50610ad8575b5083519651168652511515602086015251151590840152516060830152516080820152f35b808852808352808452808652865288610ab3565b9050158a610aad565b634e487b7160e01b835260418652602483fd5b83823461055b57606036600319011261055b5761011690610b37610b2a610baa565b60443590602435906112b2565b905191829182610bdb565b83823461055b578060031936011261055b5760e090610b70610b62610baa565b610b6a610bc5565b9061143e565b95969193909482519760018060a01b031688521515602088015215159086015260608501526080840152151560a0830152151560c0820152f35b600435906001600160a01b0382168203610bc057565b600080fd5b602435906001600160a01b0382168203610bc057565b6020908160408183019282815285518094520193019160005b828110610c02575050505090565b83516001600160a01b031685529381019392810192600101610bf4565b6000546001600160a01b03163303610c3357565b60405163118cdaa760e01b8152336004820152602490fd5b90601f8019910116810190811067ffffffffffffffff821117610c6d57604052565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03163b15610c9457565b6040516303777f6960e51b8152600490fd5b91908203918211610cb357565b634e487b7160e01b600052601160045260246000fd5b90610cd382610f80565b909290918215848115610d3e575b50610d2e57610cf08483611103565b9081151580610d23575b610d049093610d5d565b6000915042811115610d1f57610d1c91504290610ca6565b90565b5090565b506003821615610cfa565b6000935083925082915081908190565b6001600160a01b031615905038610ce1565b91908201809211610cb357565b9060046020610d6b84610e04565b6040516346706c2960e01b815290949092839182906001600160a01b03165afa908115610df857600091610dc7575b50620151809283810290808204851490151715610cb357610dba91610d50565b918201808311610cb35790565b906020823d8211610df0575b81610de060209383610c4b565b8101031261088f57505138610d9a565b3d9150610dd3565b6040513d6000823e3d90fd5b610e0d81610ea8565b15610e8a576040516346706c2960e01b815290602090829060049082906001600160a01b03165afa908115610df857600091610e57575b50610e53620151809142610ca6565b0490565b906020823d8211610e82575b81610e7060209383610c4b565b8101031261088f575051610e53610e44565b3d9150610e63565b50600090565b90816020910312610bc057518015158103610bc05790565b6040516367cbdec360e01b8152906020906001600160a01b03168183600481845afa928315610df857600093610f42575b5082610ee457505090565b6040516346706c2960e01b815292508190839060049082905afa908115610df857600091610f16575b50905042101590565b82813d8311610f3b575b610f2a8183610c4b565b8101031261088f5750518038610f0d565b503d610f20565b610f5a919350823d8411610682576106728183610c4b565b9138610ed9565b90816020910312610bc057516001600160a01b0381168103610bc05790565b610f8981610ea8565b156110fa57610f9781610e04565b6040805163629f0dc960e11b81529093916020916001600160a01b03851691908381600481865afa9081156110b6576000916110cd575b508110156110c157855163749c49f760e11b8152908382600481865afa9182156110b657600092611087575b50811561107a57906024849288519485938492630e2c6b6160e41b84520660048301525afa91821561106f5761103d93949550600092611052575b505092610d5d565b90421015908161104b575090565b9050421090565b6110689250803d106101885761017a8183610c4b565b3880611035565b85513d6000823e3d90fd5b5060009550859450505050565b90918482813d83116110af575b61109e8183610c4b565b8101031261088f5750519038610ffa565b503d611094565b87513d6000823e3d90fd5b50600094508493505050565b908482813d83116110f3575b6110e38183610c4b565b8101031261088f57505138610fce565b503d6110d9565b50600090600090565b9061110d82610ea8565b156112285760405163a01986a760e01b81526001600160a01b039182166004820152602092918216918382602481865afa918215610df8576000926111f9575b5081156111f0576000198201918211610cb35761116990610e04565b918183106111f057836004916040519283809263749c49f760e11b82525afa938415610df8576000946111bf575b505082156111b7576111a891610ca6565b0460018101809111610cb35790565b505050600090565b8181959293953d83116111e9575b6111d78183610c4b565b8101031261088f575051913880611197565b503d6111cd565b50505050600090565b90918482813d8311611221575b6112108183610c4b565b8101031261088f575051903861114d565b503d611206565b5050600090565b67ffffffffffffffff8111610c6d5760051b60200190565b906112518261122f565b61125e6040519182610c4b565b828152809261126f601f199161122f565b0190602036910137565b6000198114610cb35760010190565b805182101561129c5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b929190926112bf81610c83565b6040805163749c49f760e11b815260049391926001600160a01b03929083169160209182828881875afa91821561143357600092611404575b50818910156113c15761131f916113108a9283610d50565b908082116113b9575b50610ca6565b9461132986611247565b9760005b87811061133e575050505050505050565b6113488183610d50565b875190630e2c6b6160e41b8252848201528481602481895afa9081156113ae579087838d6113849594600094611389575b509061015491611288565b61132d565b610154929194506113a6908a3d8c116101885761017a8183610c4b565b939091611379565b88513d6000823e3d90fd5b905038611319565b5050949550505080519283019183831067ffffffffffffffff8411176113ef57505260008152600036813790565b604190634e487b7160e01b6000525260246000fd5b90918382813d831161142c575b61141b8183610c4b565b8101031261088f57505190386112f8565b503d611411565b86513d6000823e3d90fd5b91909161144a81610c83565b61145381610cc9565b93969295919490929190861588811561154e575b5061153657604051634e79043360e11b81526001600160a01b038481166004830152898116602483015260209216908281604481855afa908115610df8576114ec9284928c92600091611519575b5060405163183e35db60e21b81526001600160a01b0398891660048201529290971660248301529092839190829081906044820190565b03915afa918215610df85760009261150357505090565b610d1c9250803d10610682576106728183610c4b565b6115309150843d8611610682576106728183610c4b565b386114b5565b50955050505050506000906000908180918180918190565b6001600160a01b03161590503861146756fea26469706673582212205adcc23b2ea9f1125579d20b05624089606f7c92d3af9f0bfdc28eff79137d6364736f6c63430008140033

Deployed ByteCode

0x60406080815260048036101561001457600080fd5b600091823560e01c80631d0d856d14610b425780633c4d4d5014610b0857806351bd7b8e14610a1a5780636f39eb1114610892578063715018a6146108355780637acbbdae146106c65780638138e5ac1461055f5780638da5cb5b146105335780639330edd5146103725780639a68c81914610265578063f2fde38b146101de5763f3df535f146100a457600080fd5b346101da576020806003193601126101d6576100be610baa565b6100c781610c83565b825163749c49f760e11b8152916001600160a01b039182169080848781855afa9384156101cc578794610199575b506100ff84611247565b95875b85811061011a578651806101168a82610bdb565b0390f35b8651630e2c6b6160e41b81528281018290528381602481885afa90811561018f579061015d92918b91610162575b5086610154838c611288565b91169052611279565b610102565b6101829150853d8711610188575b61017a8183610c4b565b810190610f61565b38610148565b503d610170565b88513d8c823e3d90fd5b9080945081813d83116101c5575b6101b18183610c4b565b810103126101c1575192386100f5565b8680fd5b503d6101a7565b85513d89823e3d90fd5b8380fd5b8280fd5b5090346101da5760203660031901126101da576101f9610baa565b90610202610c1f565b6001600160a01b0391821692831561024f57505082546001600160a01b0319811683178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b51631e4fbdf760e01b8152908101849052602490fd5b50346101da57806003193601126101da57602491610281610baa565b90602061028c610bc5565b9161029684610c83565b845163a01986a760e01b81526001600160a01b0384811692820192909252958691829086165afa93841561036857859461032f575b50936102d960a09583611103565b908115159283610323575b6102ed81610ea8565b1561031c576102fc9150610e04565b925b80519480151586526020860152840152151560608301526080820152f35b50926102fe565b600383161593506102e4565b9093506020813d8211610360575b8161034a60209383610c4b565b8101031261035c5751926102d96102cb565b8480fd5b3d915061033d565b83513d87823e3d90fd5b5090346101da57602091826003193601126101d65761038f610baa565b61039881610c83565b8151635a4d30cd60e01b8152936001600160a01b0391909116919080858581865afa9485156105295786956104f6575b50815163588241c960e11b81529080828681875afa9182156104805787926104c7575b5082516304dce4e160e41b81529381858781845afa9485156104bd57889561048a575b5081908451968780926302c8de7960e11b82525afa94851561048057879561044d575b5060809650620151808351960486528501528301526060820152f35b9080955081813d8311610479575b6104658183610c4b565b810103126101c15760809650519338610431565b503d61045b565b83513d89823e3d90fd5b9094508181813d83116104b6575b6104a28183610c4b565b810103126104b25751938161040e565b8780fd5b503d610498565b84513d8a823e3d90fd5b9080925081813d83116104ef575b6104df8183610c4b565b810103126101c1575190386103eb565b503d6104d5565b9080955081813d8311610522575b61050e8183610c4b565b8101031261051e575193386103c8565b8580fd5b503d610504565b82513d88823e3d90fd5b83823461055b578160031936011261055b57905490516001600160a01b039091168152602090f35b5080fd5b50346101da5760603660031901126101da57610579610baa565b90610582610bc5565b6044356001600160a01b0380821682036101c15761059f85610c83565b8351634e79043360e11b81526001600160a01b03808516888301908152908416602082810191909152919691949192831691908590889081906040010381855afa9687156106bc578997610693575b50855163183e35db60e21b81526001600160a01b039182169881019889529084166020890152959684918791829081906040015b03915afa9485156106895760609795610654575b509061064191611103565b9282519415158552151590840152820152f35b6106419291955061067a90843d8611610682575b6106728183610c4b565b810190610e90565b949091610636565b503d610668565b84513d89823e3d90fd5b61062297509184916106b28794853d8711610682576106728183610c4b565b98509150916105ee565b86513d8b823e3d90fd5b5090346101da57816003193601126101da576106e0610baa565b91602435926106ee81610c83565b8151631a13e1e760e21b8152808401859052936001600160a01b0391909116929060208086602481885afa958615610689578796610806575b508351631ac57d5560e01b8152838101839052918183602481895afa9283156107fc5788936107ca575b50602482939486519788938492630d72ffff60e21b84528301525afa9384156107c057869461078d575b50606095508251948552840152820152f35b9080945081813d83116107b9575b6107a58183610c4b565b8101031261051e576060955051923861077b565b503d61079b565b83513d88823e3d90fd5b9180935082813d83116107f5575b6107e28183610c4b565b810103126104b257905191906024610751565b503d6107d8565b85513d8a823e3d90fd5b9080965081813d831161082e575b61081e8183610c4b565b810103126101c157519438610727565b503d610814565b833461088f578060031936011261088f5761084e610c1f565b80546001600160a01b03198116825581906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b5090346101da57602091826003193601126101d6576108af610baa565b6108b881610c83565b81516367cbdec360e01b8152936001600160a01b0391909116919080858581865afa9485156105295786956109fb575b5081516346706c2960e01b81529080828681875afa9182156104805787926109cc575b50825163629f0dc960e11b81529381858781845afa9485156104bd57889561099d575b50819084519687809263749c49f760e11b82525afa94851561048057879561096a575b5060809650825195151586528501528301526060820152f35b9080955081813d8311610996575b6109828183610c4b565b810103126101c15760809650519338610951565b503d610978565b9094508181813d83116109c5575b6109b58183610c4b565b810103126104b25751938161092e565b503d6109ab565b9080925081813d83116109f4575b6109e48183610c4b565b810103126101c15751903861090b565b503d6109da565b81610a139296503d8711610682576106728183610c4b565b93386108e8565b50823461088f57602036600319011261088f57610a35610baa565b9082519260a0840184811067ffffffffffffffff821117610af55760a09550815281845260208401828152818501908382526060860193808552610a886080880196828852610a8381610c83565b610cc9565b8a5288521515855215801580855260001960018c1b01928316808b5292939290610aec575b50610ad8575b5083519651168652511515602086015251151590840152516060830152516080820152f35b808852808352808452808652865288610ab3565b9050158a610aad565b634e487b7160e01b835260418652602483fd5b83823461055b57606036600319011261055b5761011690610b37610b2a610baa565b60443590602435906112b2565b905191829182610bdb565b83823461055b578060031936011261055b5760e090610b70610b62610baa565b610b6a610bc5565b9061143e565b95969193909482519760018060a01b031688521515602088015215159086015260608501526080840152151560a0830152151560c0820152f35b600435906001600160a01b0382168203610bc057565b600080fd5b602435906001600160a01b0382168203610bc057565b6020908160408183019282815285518094520193019160005b828110610c02575050505090565b83516001600160a01b031685529381019392810192600101610bf4565b6000546001600160a01b03163303610c3357565b60405163118cdaa760e01b8152336004820152602490fd5b90601f8019910116810190811067ffffffffffffffff821117610c6d57604052565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03163b15610c9457565b6040516303777f6960e51b8152600490fd5b91908203918211610cb357565b634e487b7160e01b600052601160045260246000fd5b90610cd382610f80565b909290918215848115610d3e575b50610d2e57610cf08483611103565b9081151580610d23575b610d049093610d5d565b6000915042811115610d1f57610d1c91504290610ca6565b90565b5090565b506003821615610cfa565b6000935083925082915081908190565b6001600160a01b031615905038610ce1565b91908201809211610cb357565b9060046020610d6b84610e04565b6040516346706c2960e01b815290949092839182906001600160a01b03165afa908115610df857600091610dc7575b50620151809283810290808204851490151715610cb357610dba91610d50565b918201808311610cb35790565b906020823d8211610df0575b81610de060209383610c4b565b8101031261088f57505138610d9a565b3d9150610dd3565b6040513d6000823e3d90fd5b610e0d81610ea8565b15610e8a576040516346706c2960e01b815290602090829060049082906001600160a01b03165afa908115610df857600091610e57575b50610e53620151809142610ca6565b0490565b906020823d8211610e82575b81610e7060209383610c4b565b8101031261088f575051610e53610e44565b3d9150610e63565b50600090565b90816020910312610bc057518015158103610bc05790565b6040516367cbdec360e01b8152906020906001600160a01b03168183600481845afa928315610df857600093610f42575b5082610ee457505090565b6040516346706c2960e01b815292508190839060049082905afa908115610df857600091610f16575b50905042101590565b82813d8311610f3b575b610f2a8183610c4b565b8101031261088f5750518038610f0d565b503d610f20565b610f5a919350823d8411610682576106728183610c4b565b9138610ed9565b90816020910312610bc057516001600160a01b0381168103610bc05790565b610f8981610ea8565b156110fa57610f9781610e04565b6040805163629f0dc960e11b81529093916020916001600160a01b03851691908381600481865afa9081156110b6576000916110cd575b508110156110c157855163749c49f760e11b8152908382600481865afa9182156110b657600092611087575b50811561107a57906024849288519485938492630e2c6b6160e41b84520660048301525afa91821561106f5761103d93949550600092611052575b505092610d5d565b90421015908161104b575090565b9050421090565b6110689250803d106101885761017a8183610c4b565b3880611035565b85513d6000823e3d90fd5b5060009550859450505050565b90918482813d83116110af575b61109e8183610c4b565b8101031261088f5750519038610ffa565b503d611094565b87513d6000823e3d90fd5b50600094508493505050565b908482813d83116110f3575b6110e38183610c4b565b8101031261088f57505138610fce565b503d6110d9565b50600090600090565b9061110d82610ea8565b156112285760405163a01986a760e01b81526001600160a01b039182166004820152602092918216918382602481865afa918215610df8576000926111f9575b5081156111f0576000198201918211610cb35761116990610e04565b918183106111f057836004916040519283809263749c49f760e11b82525afa938415610df8576000946111bf575b505082156111b7576111a891610ca6565b0460018101809111610cb35790565b505050600090565b8181959293953d83116111e9575b6111d78183610c4b565b8101031261088f575051913880611197565b503d6111cd565b50505050600090565b90918482813d8311611221575b6112108183610c4b565b8101031261088f575051903861114d565b503d611206565b5050600090565b67ffffffffffffffff8111610c6d5760051b60200190565b906112518261122f565b61125e6040519182610c4b565b828152809261126f601f199161122f565b0190602036910137565b6000198114610cb35760010190565b805182101561129c5760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b929190926112bf81610c83565b6040805163749c49f760e11b815260049391926001600160a01b03929083169160209182828881875afa91821561143357600092611404575b50818910156113c15761131f916113108a9283610d50565b908082116113b9575b50610ca6565b9461132986611247565b9760005b87811061133e575050505050505050565b6113488183610d50565b875190630e2c6b6160e41b8252848201528481602481895afa9081156113ae579087838d6113849594600094611389575b509061015491611288565b61132d565b610154929194506113a6908a3d8c116101885761017a8183610c4b565b939091611379565b88513d6000823e3d90fd5b905038611319565b5050949550505080519283019183831067ffffffffffffffff8411176113ef57505260008152600036813790565b604190634e487b7160e01b6000525260246000fd5b90918382813d831161142c575b61141b8183610c4b565b8101031261088f57505190386112f8565b503d611411565b86513d6000823e3d90fd5b91909161144a81610c83565b61145381610cc9565b93969295919490929190861588811561154e575b5061153657604051634e79043360e11b81526001600160a01b038481166004830152898116602483015260209216908281604481855afa908115610df8576114ec9284928c92600091611519575b5060405163183e35db60e21b81526001600160a01b0398891660048201529290971660248301529092839190829081906044820190565b03915afa918215610df85760009261150357505090565b610d1c9250803d10610682576106728183610c4b565b6115309150843d8611610682576106728183610c4b565b386114b5565b50955050505050506000906000908180918180918190565b6001600160a01b03161590503861146756fea26469706673582212205adcc23b2ea9f1125579d20b05624089606f7c92d3af9f0bfdc28eff79137d6364736f6c63430008140033