ETH Price: $3,112.20 (+1.35%)
Gas: 6 Gwei

Contract

0x64C7d8C8Abf28Daf9D441c507CfE9Be678A0929c
 

Overview

ETH Balance

31.902894252249611788 ETH

Eth Value

$99,288.21 (@ $3,112.20/ETH)

Token Holdings

More Info

Private Name Tags

TokenTracker

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Redeem202383542024-07-05 5:55:594 days ago1720158959IN
0x64C7d8C8...678A0929c
0 ETH0.00059713.81966134
Redeem199758972024-05-29 13:44:5941 days ago1716990299IN
0x64C7d8C8...678A0929c
0 ETH0.0007553917.48103388
Redeem199616962024-05-27 14:06:5943 days ago1716818819IN
0x64C7d8C8...678A0929c
0 ETH0.0010214623.64511011
Redeem199541132024-05-26 12:40:3544 days ago1716727235IN
0x64C7d8C8...678A0929c
0 ETH0.000317567.35108537
Redeem199402562024-05-24 14:11:5946 days ago1716559919IN
0x64C7d8C8...678A0929c
0 ETH0.000403969.35369273
Transfer199357382024-05-23 23:03:3547 days ago1716505415IN
0x64C7d8C8...678A0929c
0 ETH0.000340439.9384911
Transfer199357322024-05-23 23:02:2347 days ago1716505343IN
0x64C7d8C8...678A0929c
0 ETH0.0003459410.09951809
Transfer199357312024-05-23 23:02:1147 days ago1716505331IN
0x64C7d8C8...678A0929c
0 ETH0.0003572310.4289984
Redeem199309802024-05-23 7:06:1147 days ago1716447971IN
0x64C7d8C8...678A0929c
0 ETH0.000292376.76617412
Redeem199203772024-05-21 19:29:5949 days ago1716319799IN
0x64C7d8C8...678A0929c
0 ETH0.0007328716.9693459
Redeem199200762024-05-21 18:29:4749 days ago1716316187IN
0x64C7d8C8...678A0929c
0 ETH0.0007647217.70204508
Transfer199145972024-05-21 0:06:3550 days ago1716249995IN
0x64C7d8C8...678A0929c
0 ETH0.0004642213.55724224
Redeem199094032024-05-20 6:38:5950 days ago1716187139IN
0x64C7d8C8...678A0929c
0 ETH0.000110962.56936965
Redeem198978832024-05-18 16:00:5952 days ago1716048059IN
0x64C7d8C8...678A0929c
0 ETH0.000158713.67286869
Redeem198978142024-05-18 15:46:5952 days ago1716047219IN
0x64C7d8C8...678A0929c
0 ETH0.000131843.05103991
Redeem198963312024-05-18 10:48:1152 days ago1716029291IN
0x64C7d8C8...678A0929c
0 ETH0.000143723.32791469
Redeem198889552024-05-17 10:00:1153 days ago1715940011IN
0x64C7d8C8...678A0929c
0 ETH0.000355658.23270788
Redeem198889482024-05-17 9:58:4753 days ago1715939927IN
0x64C7d8C8...678A0929c
0 ETH0.000338677.83958439
Transfer198889432024-05-17 9:57:4753 days ago1715939867IN
0x64C7d8C8...678A0929c
0 ETH0.000213336.2280737
Redeem198889182024-05-17 9:52:4753 days ago1715939567IN
0x64C7d8C8...678A0929c
0 ETH0.000353098.17120393
Transfer198852932024-05-16 21:42:5954 days ago1715895779IN
0x64C7d8C8...678A0929c
0 ETH0.000155983.9966259
Redeem198802952024-05-16 4:56:5954 days ago1715835419IN
0x64C7d8C8...678A0929c
0 ETH0.000138113.19611387
Redeem198771982024-05-15 18:32:5955 days ago1715797979IN
0x64C7d8C8...678A0929c
0 ETH0.000390029.02581788
Approve198771112024-05-15 18:15:3555 days ago1715796935IN
0x64C7d8C8...678A0929c
0 ETH0.000330567.39557562
Redeem198742392024-05-15 8:39:2355 days ago1715762363IN
0x64C7d8C8...678A0929c
0 ETH0.000375288.68706602
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To Value
202383542024-07-05 5:55:594 days ago1720158959
0x64C7d8C8...678A0929c
0.07092343 ETH
199758972024-05-29 13:44:5941 days ago1716990299
0x64C7d8C8...678A0929c
0.15571654 ETH
199616962024-05-27 14:06:5943 days ago1716818819
0x64C7d8C8...678A0929c
0.06727702 ETH
199541132024-05-26 12:40:3544 days ago1716727235
0x64C7d8C8...678A0929c
0.07910807 ETH
199402562024-05-24 14:11:5946 days ago1716559919
0x64C7d8C8...678A0929c
5.5239275 ETH
199309802024-05-23 7:06:1147 days ago1716447971
0x64C7d8C8...678A0929c
0.51958932 ETH
199203772024-05-21 19:29:5949 days ago1716319799
0x64C7d8C8...678A0929c
0.02243864 ETH
199200762024-05-21 18:29:4749 days ago1716316187
0x64C7d8C8...678A0929c
0.07987913 ETH
199094032024-05-20 6:38:5950 days ago1716187139
0x64C7d8C8...678A0929c
0.06134321 ETH
198978832024-05-18 16:00:5952 days ago1716048059
0x64C7d8C8...678A0929c
13.94946338 ETH
198978142024-05-18 15:46:5952 days ago1716047219
0x64C7d8C8...678A0929c
0.37115396 ETH
198963312024-05-18 10:48:1152 days ago1716029291
0x64C7d8C8...678A0929c
0.03754652 ETH
198889552024-05-17 10:00:1153 days ago1715940011
0x64C7d8C8...678A0929c
0.22444797 ETH
198889482024-05-17 9:58:4753 days ago1715939927
0x64C7d8C8...678A0929c
0.11224746 ETH
198889182024-05-17 9:52:4753 days ago1715939567
0x64C7d8C8...678A0929c
0.3196561 ETH
198802952024-05-16 4:56:5954 days ago1715835419
0x64C7d8C8...678A0929c
0.21780425 ETH
198771982024-05-15 18:32:5955 days ago1715797979
0x64C7d8C8...678A0929c
0.36721102 ETH
198742392024-05-15 8:39:2355 days ago1715762363
0x64C7d8C8...678A0929c
0.08624556 ETH
198737662024-05-15 7:04:2355 days ago1715756663
0x64C7d8C8...678A0929c
1.00512375 ETH
198716682024-05-15 0:03:1156 days ago1715731391
0x64C7d8C8...678A0929c
0.07175067 ETH
198709162024-05-14 21:31:1156 days ago1715722271
0x64C7d8C8...678A0929c
0.30071739 ETH
198703672024-05-14 19:40:2356 days ago1715715623
0x64C7d8C8...678A0929c
0.11657311 ETH
198701842024-05-14 19:03:3556 days ago1715713415
0x64C7d8C8...678A0929c
0.21597091 ETH
198701222024-05-14 18:51:1156 days ago1715712671
0x64C7d8C8...678A0929c
0.58104308 ETH
198700742024-05-14 18:41:1156 days ago1715712071
0x64C7d8C8...678A0929c
0.02771895 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
KotoV3

Compiler Version
v0.8.23+commit.f704f362

Optimization Enabled:
Yes with 200 runs

Other Settings:
shanghai EvmVersion, MIT license
File 1 of 7 : KotoV3.sol
// SPDX-License-Identifier: MIT

///@title Koto ERC20 Token
///@author Izanagi Dev
///@notice A stripped down ERC20 tax token that implements automated and continious monetary policy decisions.
///@dev Bonds are the ERC20 token in exchange for Ether. Unsold bonds with automatically be burned.
/// The bonding schedule is set to attempt to sell all of the tokens held within the contract in 1 day intervals. Taking a snapshot
/// of the amount currently held within the contract at the start of the next internal period, using this amount as the capcipty to be sold.

/// Socials
/// Telegram: https://t.me/KotoPortal

pragma solidity 0.8.23;

import {PricingLibrary} from "./PricingLibrary.sol";
import {SafeTransferLib} from "lib/solmate/src/utils/SafeTransferLib.sol";
import {FullMath} from "./libraries/FullMath.sol";
import {IERC20Minimal} from "./interfaces/IERC20Minimal.sol";
import {IKotoV3} from "./interfaces/IKotoV3.sol";

contract KotoV3 is IKotoV3 {
    // ========================== STORAGE ========================== \\

    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    mapping(address => bool) private _excluded;
    mapping(address => bool) private _amms;
    uint256 private _totalSupply;

    // ====================== ETH BOND STORAGE ===================== \\

    PricingLibrary.Adjustment private adjustment;
    PricingLibrary.Data private data;
    PricingLibrary.Market private market;
    PricingLibrary.Term private term;

    // ====================== LP BOND STORAGE ====================== \\

    PricingLibrary.Adjustment private lpAdjustment;
    PricingLibrary.Data private lpData;
    PricingLibrary.Market private lpMarket;
    PricingLibrary.Term private lpTerm;

    uint256 ethCapacityNext;
    uint256 lpCapacityNext;

    uint8 private locked;
    bool private launched;

    // =================== CONSTANTS / IMMUTABLES =================== \\

    string private constant NAME = "Koto";
    string private constant SYMBOL = "KOTO";
    uint8 private constant DECIMALS = 18;
    ///@dev flat 5% tax for buys and sells
    uint8 private constant FEE = 50;
    bool private immutable zeroForOne;
    address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
    address private constant UNISWAP_V2_FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
    address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    address private constant OWNER = 0x946eF43867225695E29241813A8F41519634B36b;
    address private constant BOND_DEPOSITORY = 0xE58B33c813ac4077bd2519dE90FccB189a19FA71;
    address private immutable pair;
    address private immutable token0;
    address private immutable token1;
    uint256 private constant INTERVAL = 604800; // 7 days in seconds

    // ========================== MODIFIERS ========================== \\

    modifier lock() {
        if (locked == 2) revert Reentrancy();
        locked = 2;
        _;
        locked = 1;
    }

    // ========================= CONTRUCTOR ========================= \\

    constructor() {
        pair = _createUniswapV2Pair(address(this), WETH);
        _excluded[OWNER] = true;
        _excluded[BOND_DEPOSITORY] = true;
        _excluded[address(this)] = true;
        _amms[pair] = true;
        _mint(OWNER, IERC20Minimal(0xc75c635c1F5e21D23eC8592Cb37503B82A7EF942).totalSupply());
        (token0, token1) = _getTokens(pair);
        zeroForOne = address(this) == token0 ? true : false;
        _allowances[address(this)][UNISWAP_V2_ROUTER] = type(uint256).max;
    }

    // ==================== EXTERNAL FUNCTIONS ===================== \\

    function transfer(address _to, uint256 _value) public returns (bool success) {
        if (_to == address(0) || _value == 0) revert InvalidTransfer();
        _transfer(msg.sender, _to, _value);
        return true;
    }

    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
        if (_to == address(0) || _value == 0) revert InvalidTransfer();
        if (_from != msg.sender) {
            if (_allowances[_from][msg.sender] < _value) revert InsufficentAllowance();
            _allowances[_from][msg.sender] -= _value;
        }
        _transfer(_from, _to, _value);
        return true;
    }

    function approve(address _spender, uint256 _value) public returns (bool success) {
        address owner = msg.sender;
        _allowances[owner][_spender] = _value;
        return true;
    }

    ///@notice exchange ETH for Koto tokens at the current bonding price
    ///@dev bonds are set on 1 day intervals with 4 hour deposit intervals and 30 minute tune intervals.
    function bond() public payable lock returns (uint256 payout) {
        if (block.timestamp > term.conclusion) revert MarketClosed();
        if (market.capacity != 0) {
            // Cache variables for later use to minimize storage calls
            PricingLibrary.Market memory _market = market;
            PricingLibrary.Term memory _term = term;
            PricingLibrary.Data memory _data = data;
            PricingLibrary.Adjustment memory adjustments = adjustment;
            uint256 _supply = _totalSupply;
            uint48 time = uint48(block.timestamp);

            // Can pass in structs here as nothing has been updated yet
            (_market, _data, _term, adjustments) = PricingLibrary.decay(data, _market, _term, adjustments);

            uint256 price = PricingLibrary.marketPrice(_term.controlVariable, _market.totalDebt, _supply);

            payout = (msg.value * 1e18 / price);
            if (payout > market.maxPayout) revert MaxPayout();

            // Update market variables
            _market.capacity -= uint96(payout);
            _market.purchased += uint96(msg.value);
            _market.sold += uint96(payout);
            _market.totalDebt += uint96(payout);

            bool success = _bond(msg.sender, payout);
            if (!success) revert BondFailed();
            emit Bond(msg.sender, payout, price);

            //Touches market, data, terms, and adjustments
            (_market, _term, _data, adjustments) =
                PricingLibrary.tune(time, _market, _term, _data, adjustments, _supply);

            // Write changes to storage.
            market = _market;
            term = _term;
            data = _data;
            adjustment = adjustments;
        } else {
            //If bonds are not available refund the eth sent to the contract
            SafeTransferLib.safeTransferETH(msg.sender, msg.value);
        }
    }

    function bondLp(uint256 _lpAmount) public lock returns (uint256 payout) {
        if (block.timestamp > lpTerm.conclusion) revert MarketClosed();
        if (lpMarket.capacity != 0) {
            IERC20Minimal(pair).transferFrom(msg.sender, address(BOND_DEPOSITORY), _lpAmount);
            // Cache variables for later use to minimize storage calls
            PricingLibrary.Market memory _market = lpMarket;
            PricingLibrary.Term memory _term = lpTerm;
            PricingLibrary.Data memory _data = lpData;
            PricingLibrary.Adjustment memory adjustments = lpAdjustment;
            uint256 _supply = _totalSupply;
            uint48 time = uint48(block.timestamp);

            // Can pass in structs here as nothing has been updated yet
            (_market, _data, _term, adjustments) = PricingLibrary.decay(lpData, _market, _term, adjustments);

            uint256 price = PricingLibrary.marketPrice(_term.controlVariable, _market.totalDebt, _supply);

            payout = (_lpAmount * 1e18 / price);
            if (payout > lpMarket.maxPayout) revert MaxPayout();

            // Update market variables
            _market.capacity -= uint96(payout);
            _market.purchased += uint96(_lpAmount);
            _market.sold += uint96(payout);
            _market.totalDebt += uint96(payout);

            bool success = _bond(msg.sender, payout);
            if (!success) revert BondFailed();
            emit Bond(msg.sender, payout, price);

            //Touches market, data, terms, and adjustments
            (_market, _term, _data, adjustments) =
                PricingLibrary.tune(time, _market, _term, _data, adjustments, _supply);

            // Write changes to storage.
            lpMarket = _market;
            lpTerm = _term;
            lpData = _data;
            lpAdjustment = adjustments;
        }
    }

    ///@notice burn Koto tokens in exchange for a piece of the underlying reserves
    ///@param amount The amount of Koto tokens to redeem
    ///@return payout The amount of ETH received in exchange for the Koto tokens
    function redeem(uint256 amount) external returns (uint256 payout) {
        // Underlying reserves per token
        uint256 price = FullMath.mulDiv(address(this).balance, 1e18, _totalSupply);
        payout = FullMath.mulDiv(price, amount, 1e18);
        _burn(msg.sender, amount);
        SafeTransferLib.safeTransferETH(msg.sender, payout);
        emit Redeem(msg.sender, amount, payout, price);
    }

    ///@notice burn Koto tokens, without redemption
    ///@param amount the amount of Koto to burn
    function burn(uint256 amount) external returns (bool success) {
        _burn(msg.sender, amount);
        success = true;
        emit Transfer(msg.sender, address(0), amount);
    }

    // ==================== EXTERNAL VIEW FUNCTIONS ===================== \\

    ///@notice get the tokens name
    function name() public pure returns (string memory) {
        return NAME;
    }

    ///@notice get the tokens symbol
    function symbol() public pure returns (string memory) {
        return SYMBOL;
    }

    ///@notice get the tokens decimals
    function decimals() public pure returns (uint8) {
        return DECIMALS;
    }

    ///@notice get the tokens total supply
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    ///@notice get the current balance of a user
    ///@param _owner the user whos balance you want to check
    function balanceOf(address _owner) public view returns (uint256) {
        return _balances[_owner];
    }

    ///@notice get current approved amount for transfer from another party
    ///@param owner the current owner of the tokens
    ///@param spender the user who has approval (or not) to spend the owners tokens
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    ///@notice return the Uniswap V2 Pair address
    function pool() external view returns (address) {
        return pair;
    }

    ///@notice get the owner of the contract
    ///@dev ownership is nontransferable and limited to opening trade, exclusion / inclusion,s and increasing liquidity
    function ownership() external pure returns (address) {
        return OWNER;
    }

    ///@notice the current price a bond
    function bondPrice() external view returns (uint256) {
        return _currentMarketPrice(true);
    }

    function bondPriceLp() external view returns (uint256) {
        return _currentMarketPrice(false);
    }

    ///@notice return the current redemption price for 1 uint of Koto.
    function redemptionPrice() external view returns (uint256) {
        return ((address(this).balance * 1e18) / _totalSupply);
    }

    function marketInfo()
        external
        view
        returns (PricingLibrary.Market memory, PricingLibrary.Term memory, PricingLibrary.Data memory)
    {
        return (market, term, data);
    }

    function lpMarketInfo()
        external
        view
        returns (PricingLibrary.Market memory, PricingLibrary.Term memory, PricingLibrary.Data memory)
    {
        return (lpMarket, lpTerm, lpData);
    }

    function depository() external pure returns (address) {
        return BOND_DEPOSITORY;
    }

    // ========================= ADMIN FUNCTIONS ========================= \\

    ///@notice remove a given address from fees and limits
    ///@param user the user to exclude from fees
    ///@dev this is a one way street so once a user has been excluded they can not then be removed
    function exclude(address user) external {
        if (msg.sender != OWNER) revert OnlyOwner();
        _excluded[user] = true;
        emit UserExcluded(user);
    }

    ///@notice add a amm pool / pair
    ///@param _pool the address of the pool / pair to add
    function addAmm(address _pool) external {
        if (msg.sender != OWNER) revert OnlyOwner();
        _amms[_pool] = true;
        emit AmmAdded(_pool);
    }

    ///@notice seed the initial liquidity from this contract.
    function launch() external {
        if (msg.sender != OWNER) revert OnlyOwner();
        if (launched) revert AlreadyLaunched();
        _addInitialLiquidity();
        launched = true;
        emit Launched(block.timestamp);
    }

    ///@notice create a new bond market for ETH and LP bonds
    ///@param ethBondAmount the amount of koto tokens to be sold for ETH bonds during this period
    ///@param lpBondAmount the amount of koto tokens to be sold for LP bonds during this period.
    function create(uint256 ethBondAmount, uint256 lpBondAmount) external {
        if (msg.sender != OWNER && msg.sender != BOND_DEPOSITORY) revert InvalidSender();
        if (term.conclusion > block.timestamp) revert OngoingBonds();

        ///@dev clear the current unsold bonds in order to prevent build up of unsold tokens
        /// if this is not done over a longer time period it would effect the redemption rate for users.
        uint256 currentBalance = _balances[address(this)];
        if (currentBalance > 0) {
            unchecked {
                _balances[address(this)] -= currentBalance;
                _totalSupply -= currentBalance;
            }
            emit Transfer(address(this), address(0), currentBalance);
        }
        uint256 total = ethBondAmount + lpBondAmount;
        transferFrom(msg.sender, address(this), total);
        ethCapacityNext = ethBondAmount;
        lpCapacityNext = lpBondAmount;
        _create();
        _createLpMarket();
    }

    // ========================= INTERNAL FUNCTIONS ========================= \\

    ///@notice create the Uniswap V2 Pair
    ///@param _token0 token 0 of the pair
    ///@param _token1 token 1 of the pair
    ///@return _pair the pair address
    function _createUniswapV2Pair(address _token0, address _token1) private returns (address _pair) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0xc9c6539600000000000000000000000000000000000000000000000000000000)
            mstore(add(ptr, 4), and(_token0, 0xffffffffffffffffffffffffffffffffffffffff))
            mstore(add(ptr, 36), and(_token1, 0xffffffffffffffffffffffffffffffffffffffff))
            let result := call(gas(), UNISWAP_V2_FACTORY, 0, ptr, 68, 0, 32)
            if iszero(result) { revert(0, 0) }
            _pair := mload(0x00)
        }
    }

    ///@notice add the initial liquidity of the pool.
    function _addInitialLiquidity() private {
        uint256 tokenAmount = _balances[address(this)];
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0xf305d71900000000000000000000000000000000000000000000000000000000)
            mstore(add(ptr, 4), and(address(), 0xffffffffffffffffffffffffffffffffffffffff))
            mstore(add(ptr, 36), tokenAmount)
            mstore(add(ptr, 68), 0)
            mstore(add(ptr, 100), 0)
            mstore(add(ptr, 132), BOND_DEPOSITORY)
            mstore(add(ptr, 164), timestamp())
            let result := call(gas(), UNISWAP_V2_ROUTER, balance(address()), ptr, 196, 0, 0)
            if iszero(result) { revert(0, 0) }
        }
    }

    ///@notice create the next bond market information
    ///@dev this is done automatically if the previous market conclusion has passed
    /// time check must be done elsewhere as the initial conclusion is set to uint48 max,
    /// tokens must also already be held within the contract or else the call will revert
    function _create() private {
        // Set the initial price to the current market price
        uint96 targetDebt = uint96(ethCapacityNext);
        if (ethCapacityNext > 0) {
            uint256 initialPrice = _getPrice();

            uint96 capacity = targetDebt;
            uint96 maxPayout = uint96(targetDebt * 86400 / INTERVAL);
            uint256 controlVariable = initialPrice * _totalSupply / targetDebt;
            bool policy = _policy(capacity, initialPrice);
            uint48 conclusion = uint48(block.timestamp + INTERVAL);

            if (policy) {
                market = PricingLibrary.Market(capacity, targetDebt, maxPayout, 0, 0);
                term = PricingLibrary.Term(conclusion, controlVariable);
                data =
                    PricingLibrary.Data(uint48(block.timestamp), uint48(block.timestamp), uint48(INTERVAL), 86400, 1800);
                emit CreateMarket(capacity, block.timestamp, conclusion);
            } else {
                _burn(address(this), capacity);
                // Set the markets so that they will be closed for the next interval. Important step to make sure
                // that if anyone accidently tries to buy a bond they get refunded their eth.
                term.conclusion = uint48(block.timestamp + INTERVAL);
                market.capacity = 0;
            }
        }
        ethCapacityNext = 0;
    }

    ///@notice create the next bond market for LP tokens -> koto
    function _createLpMarket() private {
        uint96 targetDebt = uint96(lpCapacityNext);
        if (targetDebt > 0) {
            uint256 initialPrice = _getLpPrice();
            uint96 capacity = targetDebt;
            uint96 maxPayout = uint96(targetDebt * 86400 / INTERVAL);
            uint256 controlVariable = initialPrice * _totalSupply / targetDebt;
            bool policy = _policy(capacity, initialPrice);
            uint48 conclusion = uint48(block.timestamp + INTERVAL);

            if (policy) {
                lpMarket = PricingLibrary.Market(capacity, targetDebt, maxPayout, 0, 0);
                lpTerm = PricingLibrary.Term(conclusion, controlVariable);
                lpData =
                    PricingLibrary.Data(uint48(block.timestamp), uint48(block.timestamp), uint48(INTERVAL), 86400, 1800);
                emit CreateMarket(capacity, block.timestamp, conclusion);
            } else {
                _burn(address(this), capacity);
                // Set the markets so that they will be closed for the next interval. Important step to make sure
                // that if anyone accidently tries to buy a bond they get refunded their eth.
                lpTerm.conclusion = uint48(block.timestamp + INTERVAL);
                lpMarket.capacity = 0;
            }
        }
        lpCapacityNext = 0;
    }

    ///@notice determines if to sell the tokens available as bonds or to burn them instead
    ///@param capacity the amount of tokens that will be available within the next bonding cycle
    ///@param price the starting price of the bonds to sell
    ///@return decision the decision reached determining which is more valuable to sell the bonds (true) or to burn them (false)
    ///@dev the decision is made optimistically using the initial price as the selling price for the deicison. If selling the tokens all at the starting
    /// price does not increase relative reserves more than burning the tokens then they are burned. If they are equivilant burning wins out.
    function _policy(uint256 capacity, uint256 price) private view returns (bool decision) {
        uint256 supply = _totalSupply;
        uint256 burnRelative = (address(this).balance * 1e18) / (supply - capacity);
        uint256 bondRelative = ((address(this).balance * 1e18) + ((capacity * price))) / supply;
        decision = burnRelative >= bondRelative ? false : true;
    }

    ///@notice internal transfer function to handle dealing with taxes
    function _transfer(address from, address to, uint256 _value) private {
        if (_value > _balances[from]) revert InsufficentBalance();
        bool fees;
        if (_amms[to] || _amms[from]) {
            if (_excluded[to] || _excluded[from]) {
                fees = false;
            } else {
                fees = true;
            }
        }
        if (fees) {
            uint256 fee = (_value * FEE) / 1000;

            unchecked {
                _balances[from] -= _value;
                _balances[BOND_DEPOSITORY] += fee;
            }
            _value -= fee;
            unchecked {
                _balances[to] += _value;
            }
        } else {
            unchecked {
                _balances[from] -= _value;
                _balances[to] += _value;
            }
        }
        emit Transfer(from, to, _value);
    }

    ///@notice mint new koto tokens
    ///@param to the user who will receive the tokens
    ///@param value the amount of tokens to mint
    ///@dev this function is used once, during the creation of the contract and is then
    /// not callable
    function _mint(address to, uint256 value) private {
        unchecked {
            _balances[to] += value;
            _totalSupply += value;
        }
        emit Transfer(address(0), to, value);
    }

    ///@notice burn koto tokens
    ///@param from the user to burn the tokens from
    ///@param value the amount of koto tokens to burn
    function _burn(address from, uint256 value) private {
        if (_balances[from] < value) revert InsufficentBalance();
        unchecked {
            _balances[from] -= value;
            _totalSupply -= value;
        }
        emit Transfer(from, address(0), value);
    }

    ///@notice send the user the correct amount of tokens after the have bought a bond
    ///@param to the user to send the tokens to
    ///@param value the amount of koto tokens to send
    ///@dev bonds are not subject to taxes
    function _bond(address to, uint256 value) private returns (bool success) {
        if (value > _balances[address(this)]) revert InsufficentBondsAvailable();
        unchecked {
            _balances[to] += value;
            _balances[address(this)] -= value;
        }
        success = true;
        emit Transfer(address(this), to, value);
    }

    ///@notice calculate the current market price based on the reserves of the Uniswap Pair
    ///@dev price is returned as the amount of ETH you would get back for 1 full (1e18) Koto tokens
    function _getPrice() private view returns (uint256 price) {
        address _pair = pair;
        uint112 reserve0;
        uint112 reserve1;
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x0902f1ac00000000000000000000000000000000000000000000000000000000)
            let success := staticcall(gas(), _pair, ptr, 4, 0, 0)
            if iszero(success) { revert(0, 0) }
            returndatacopy(0x00, 0, 32)
            returndatacopy(0x20, 0x20, 32)
            reserve0 := mload(0x00)
            reserve1 := mload(0x20)
        }

        if (zeroForOne) {
            price = FullMath.mulDiv(uint256(reserve1), 1e18, uint256(reserve0));
        } else {
            price = FullMath.mulDiv(uint256(reserve0), 1e18, uint256(reserve1));
        }
    }

    ///@notice return the current price in koto for 1 LP token
    function _getLpPrice() private view returns (uint256 _lpPrice) {
        address _pair = pair;
        uint112 reserve0;
        uint112 reserve1;
        uint256 lpTotalSupply;
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x0902f1ac00000000000000000000000000000000000000000000000000000000)
            let success := staticcall(gas(), _pair, ptr, 4, 0, 0)
            if iszero(success) { revert(0, 0) }
            returndatacopy(0x00, 0, 32)
            returndatacopy(0x20, 0x20, 32)
            reserve0 := mload(0x00)
            reserve1 := mload(0x20)
            mstore(add(ptr, 0x20), 0x18160ddd00000000000000000000000000000000000000000000000000000000)
            let result := staticcall(gas(), _pair, add(ptr, 0x20), 4, 0, 32)
            lpTotalSupply := mload(0x00)
        }
        ///@dev with uniswap v2 we simply treat the other token total as equal value to simplify the pricing mechanism
        if (zeroForOne) {
            _lpPrice = FullMath.mulDiv(reserve0 * 2, 1e18, lpTotalSupply);
        } else {
            _lpPrice = FullMath.mulDiv(reserve1 * 2, 1e18, lpTotalSupply);
        }
    }

    ///@notice return the tokens for a Uniswap V2 Pair
    ///@param _pair the address of the pair
    ///@return _token0 token 0 of the uniswap pair
    ///@return _token1 token 1 of the uniswap pair
    function _getTokens(address _pair) private view returns (address _token0, address _token1) {
        assembly {
            let ptr := mload(0x40)
            mstore(ptr, 0x0dfe168100000000000000000000000000000000000000000000000000000000)
            let resultToken0 := staticcall(gas(), _pair, ptr, 4, 0, 32)
            mstore(add(ptr, 4), 0xd21220a700000000000000000000000000000000000000000000000000000000)
            let resultToken1 := staticcall(gas(), _pair, add(ptr, 4), 4, 32, 32)
            if or(iszero(resultToken0), iszero(resultToken1)) { revert(0, 0) }
            _token0 := mload(0x00)
            _token1 := mload(0x20)
        }
    }

    ///@notice get the current market price of bonds based on decay and other factors
    ///@param eth true if you are getting the ETH bond price, false for LP bond price
    function _currentMarketPrice(bool eth) private view returns (uint256) {
        if (eth) {
            return (
                FullMath.mulDiv(
                    _currentControlVariable(term.controlVariable, adjustment),
                    PricingLibrary.debtRatio(market.totalDebt, _totalSupply),
                    1e18
                )
            );
        } else {
            return (
                FullMath.mulDiv(
                    _currentControlVariable(lpTerm.controlVariable, lpAdjustment),
                    PricingLibrary.debtRatio(lpMarket.totalDebt, _totalSupply),
                    1e18
                )
            );
        }
    }

    function _currentControlVariable(uint256 controlVariable, PricingLibrary.Adjustment memory info)
        private
        view
        returns (uint256)
    {
        (uint256 decay,,) = PricingLibrary.controlDecay(info);
        return controlVariable - decay;
    }

    receive() external payable {}
}

File 2 of 7 : PricingLibrary.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.23;

library PricingLibrary {
    // 1 Slot
    struct Data {
        uint48 lastTune;
        uint48 lastDecay; // last timestamp when market was created and debt was decayed
        uint48 length; // time from creation to conclusion. used as speed to decay debt.
        uint48 depositInterval; // target frequency of deposits
        uint48 tuneInterval; // frequency of tuning
    }

    // 2 Storage slots
    struct Market {
        uint96 capacity; // capacity remaining
        uint96 totalDebt; // total debt from market
        uint96 maxPayout; // max tokens in/out
        uint96 sold; // Koto out
        uint96 purchased; // Eth in
    }

    // 1 Storage Slot
    struct Adjustment {
        uint128 change;
        uint48 lastAdjustment;
        uint48 timeToAdjusted;
        bool active;
    }

    // 2 Storage slots
    struct Term {
        uint48 conclusion; // timestamp when the current market will end
        uint256 controlVariable; // scaling variable for price
    }

    function decay(Data memory data, Market memory market, Term memory terms, Adjustment memory adjustments)
        internal
        view
        returns (Market memory, Data memory, Term memory, Adjustment memory)
    {
        uint48 time = uint48(block.timestamp);
        market.totalDebt -= debtDecay(data, market);
        data.lastDecay = time;

        if (adjustments.active) {
            (uint128 adjustby, uint48 dt, bool stillActive) = controlDecay(adjustments);
            terms.controlVariable -= adjustby;
            if (stillActive) {
                adjustments.change -= adjustby;
                adjustments.timeToAdjusted -= dt;
                adjustments.lastAdjustment = time;
            } else {
                adjustments.active = false;
            }
        }
        return (market, data, terms, adjustments);
    }

    function controlDecay(Adjustment memory info) internal view returns (uint128, uint48, bool) {
        if (!info.active) return (0, 0, false);

        uint48 secondsSince = uint48(block.timestamp) - info.lastAdjustment;
        bool active = secondsSince < info.timeToAdjusted;
        uint128 _decay = active ? (info.change * secondsSince) / info.timeToAdjusted : info.change;
        return (_decay, secondsSince, active);
    }

    function marketPrice(uint256 _controlVariable, uint256 _totalDebt, uint256 _totalSupply)
        internal
        pure
        returns (uint256)
    {
        return ((_controlVariable * debtRatio(_totalDebt, _totalSupply)) / 1e18);
    }

    function debtRatio(uint256 _totalDebt, uint256 _totalSupply) internal pure returns (uint256) {
        return ((_totalDebt * 1e18) / _totalSupply);
    }

    function debtDecay(Data memory data, Market memory market) internal view returns (uint64) {
        uint256 secondsSince = block.timestamp - data.lastDecay;
        return uint64((market.totalDebt * secondsSince) / data.length);
    }

    struct TuneCache {
        uint256 remaining;
        uint256 price;
        uint256 capacity;
        uint256 targetDebt;
        uint256 ncv;
    }

    function tune(
        uint48 time,
        Market memory market,
        Term memory term,
        Data memory data,
        Adjustment memory adjustment,
        uint256 _totalSupply
    ) internal pure returns (Market memory, Term memory, Data memory, Adjustment memory) {
        TuneCache memory cache;
        if (time >= data.lastTune + data.tuneInterval) {
            cache.remaining = term.conclusion - time;
            cache.price = marketPrice(term.controlVariable, market.totalDebt, _totalSupply);
            cache.capacity = market.capacity;
            market.maxPayout = uint96((cache.capacity * data.depositInterval / cache.remaining));
            cache.targetDebt = cache.capacity * data.length / cache.remaining;
            cache.ncv = (cache.price * _totalSupply) / cache.targetDebt;

            if (cache.ncv < term.controlVariable) {
                uint128 change = uint128(term.controlVariable - cache.ncv);
                adjustment = Adjustment(change, time, data.tuneInterval, true);
            } else {
                term.controlVariable = cache.ncv;
            }
            data.lastTune = time;
        }
        return (market, term, data, adjustment);
    }
}

File 3 of 7 : SafeTransferLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {ERC20} from "../tokens/ERC20.sol";

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument.
            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}

File 4 of 7 : FullMath.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @title Contains 512-bit math functions
/// @notice Facilitates multiplication and division that can have overflow of an intermediate value without any loss of precision
/// @dev Handles "phantom overflow" i.e., allows multiplication and division where an intermediate value overflows 256 bits
library FullMath {
    /// @notice Calculates floor(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    /// @dev Credit to Remco Bloemen under MIT license https://xn--2-umb.com/21/muldiv
    function mulDiv(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = a * b
            // Compute the product mod 2**256 and mod 2**256 - 1
            // then use the Chinese Remainder Theorem to reconstruct
            // the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2**256 + prod0
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(a, b, not(0))
                prod0 := mul(a, b)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division
            if (prod1 == 0) {
                require(denominator > 0);
                assembly {
                    result := div(prod0, denominator)
                }
                return result;
            }

            // Make sure the result is less than 2**256.
            // Also prevents denominator == 0
            require(denominator > prod1);

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0]
            // Compute remainder using mulmod
            uint256 remainder;
            assembly {
                remainder := mulmod(a, b, denominator)
            }
            // Subtract 256 bit number from 512 bit number
            assembly {
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator
            // Compute largest power of two divisor of denominator.
            // Always >= 1.
            uint256 twos = (0 - denominator) & denominator;
            // Divide denominator by power of two
            assembly {
                denominator := div(denominator, twos)
            }

            // Divide [prod1 prod0] by the factors of two
            assembly {
                prod0 := div(prod0, twos)
            }
            // Shift in bits from prod1 into prod0. For this we need
            // to flip `twos` such that it is 2**256 / twos.
            // If twos is zero, then it becomes one
            assembly {
                twos := add(div(sub(0, twos), twos), 1)
            }
            prod0 |= prod1 * twos;

            // Invert denominator mod 2**256
            // Now that denominator is an odd number, it has an inverse
            // modulo 2**256 such that denominator * inv = 1 mod 2**256.
            // Compute the inverse by starting with a seed that is correct
            // correct for four bits. That is, denominator * inv = 1 mod 2**4
            uint256 inv = (3 * denominator) ^ 2;
            // Now use Newton-Raphson iteration to improve the precision.
            // Thanks to Hensel's lifting lemma, this also works in modular
            // arithmetic, doubling the correct bits in each step.
            inv *= 2 - denominator * inv; // inverse mod 2**8
            inv *= 2 - denominator * inv; // inverse mod 2**16
            inv *= 2 - denominator * inv; // inverse mod 2**32
            inv *= 2 - denominator * inv; // inverse mod 2**64
            inv *= 2 - denominator * inv; // inverse mod 2**128
            inv *= 2 - denominator * inv; // inverse mod 2**256

            // Because the division is now exact we can divide by multiplying
            // with the modular inverse of denominator. This will give us the
            // correct result modulo 2**256. Since the precoditions guarantee
            // that the outcome is less than 2**256, this is the final result.
            // We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inv;
            return result;
        }
    }

    /// @notice Calculates ceil(a×b÷denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
    /// @param a The multiplicand
    /// @param b The multiplier
    /// @param denominator The divisor
    /// @return result The 256-bit result
    function mulDivRoundingUp(uint256 a, uint256 b, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            result = mulDiv(a, b, denominator);
            if (mulmod(a, b, denominator) > 0) {
                require(result < type(uint256).max);
                result++;
            }
        }
    }
}

File 5 of 7 : IERC20Minimal.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.23;

interface IERC20Minimal {
    function transferFrom(address from, address to, uint256 value) external returns (bool);
    function transfer(address, uint256) external returns (bool);
    function balanceOf(address) external view returns (uint256);
    function totalSupply() external view returns (uint256);
}

File 6 of 7 : IKotoV3.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.23;

import {PricingLibrary} from "../PricingLibrary.sol";

interface IKotoV3 {
    // ==================== EXTERNAL FUNCTIONS ===================== \\

    function transfer(address _to, uint256 _value) external returns (bool success);

    function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);

    function approve(address _spender, uint256 _value) external returns (bool success);

    ///@notice exchange ETH for Koto tokens at the current bonding price
    ///@dev bonds are set on 1 day intervals with 4 hour deposit intervals and 30 minute tune intervals.
    function bond() external payable returns (uint256 payout);

    function bondLp(uint256 _lpAmount) external returns (uint256 payout);

    ///@notice burn Koto tokens in exchange for a piece of the underlying reserves
    ///@param amount The amount of Koto tokens to redeem
    ///@return payout The amount of ETH received in exchange for the Koto tokens
    function redeem(uint256 amount) external returns (uint256 payout);

    ///@notice burn Koto tokens, without redemption
    ///@param amount the amount of Koto to burn
    function burn(uint256 amount) external returns (bool success);

    // ==================== EXTERNAL VIEW FUNCTIONS ===================== \\

    ///@notice get the tokens name
    function name() external pure returns (string memory);

    ///@notice get the tokens symbol
    function symbol() external pure returns (string memory);

    ///@notice get the tokens decimals
    function decimals() external pure returns (uint8);

    ///@notice get the tokens total supply
    function totalSupply() external view returns (uint256);

    ///@notice get the current balance of a user
    ///@param _owner the user whos balance you want to check
    function balanceOf(address _owner) external view returns (uint256);

    ///@notice get current approved amount for transfer from another party
    ///@param owner the current owner of the tokens
    ///@param spender the user who has approval (or not) to spend the owners tokens
    function allowance(address owner, address spender) external view returns (uint256);

    ///@notice return the Uniswap V2 Pair address
    function pool() external view returns (address);

    ///@notice get the owner of the contract
    ///@dev ownership is nontransferable and limited to opening trade, exclusion / inclusion,s and increasing liquidity
    function ownership() external pure returns (address);

    ///@notice the current price a bond
    function bondPrice() external view returns (uint256);

    function bondPriceLp() external view returns (uint256);

    ///@notice return the current redemption price for 1 uint of Koto.
    function redemptionPrice() external view returns (uint256);

    function marketInfo()
        external
        view
        returns (PricingLibrary.Market memory, PricingLibrary.Term memory, PricingLibrary.Data memory);

    function lpMarketInfo()
        external
        view
        returns (PricingLibrary.Market memory, PricingLibrary.Term memory, PricingLibrary.Data memory);

    function depository() external pure returns (address);

    function create(uint256 ethBondAmount, uint256 lpBondAmount) external;

    // ========================= EVENTS ========================= \\

    event AmmAdded(address poolAdded);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
    event Bond(address indexed buyer, uint256 amount, uint256 bondPrice);
    event CreateMarket(uint256 bonds, uint256 start, uint48 end);
    event IncreaseLiquidity(uint256 kotoAdded, uint256 ethAdded);
    event Launched(uint256 time);
    event LimitsRemoved(uint256 time);
    event OpenBondMarket(uint256 openingTime);
    event Redeem(address indexed sender, uint256 burned, uint256 payout, uint256 floorPrice);
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event UserExcluded(address indexed userToExclude);

    // ========================= ERRORS ========================= \\

    error AlreadyLaunched();
    error BondFailed();
    error InsufficentAllowance();
    error InsufficentBalance();
    error InsufficentBondsAvailable();
    error InvalidSender();
    error InvalidTransfer();
    error LimitsReached();
    error MarketClosed();
    error MaxPayout();
    error OngoingBonds();
    error OnlyOwner();
    error RedeemFailed();
    error Reentrancy();
}

File 7 of 7 : ERC20.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "solmate/=lib/solmate/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "shanghai",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyLaunched","type":"error"},{"inputs":[],"name":"BondFailed","type":"error"},{"inputs":[],"name":"InsufficentAllowance","type":"error"},{"inputs":[],"name":"InsufficentBalance","type":"error"},{"inputs":[],"name":"InsufficentBondsAvailable","type":"error"},{"inputs":[],"name":"InvalidSender","type":"error"},{"inputs":[],"name":"InvalidTransfer","type":"error"},{"inputs":[],"name":"LimitsReached","type":"error"},{"inputs":[],"name":"MarketClosed","type":"error"},{"inputs":[],"name":"MaxPayout","type":"error"},{"inputs":[],"name":"OngoingBonds","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"RedeemFailed","type":"error"},{"inputs":[],"name":"Reentrancy","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"poolAdded","type":"address"}],"name":"AmmAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bondPrice","type":"uint256"}],"name":"Bond","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"bonds","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"start","type":"uint256"},{"indexed":false,"internalType":"uint48","name":"end","type":"uint48"}],"name":"CreateMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"kotoAdded","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"ethAdded","type":"uint256"}],"name":"IncreaseLiquidity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"Launched","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"time","type":"uint256"}],"name":"LimitsRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"openingTime","type":"uint256"}],"name":"OpenBondMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"burned","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"payout","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"floorPrice","type":"uint256"}],"name":"Redeem","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userToExclude","type":"address"}],"name":"UserExcluded","type":"event"},{"inputs":[{"internalType":"address","name":"_pool","type":"address"}],"name":"addAmm","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bond","outputs":[{"internalType":"uint256","name":"payout","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_lpAmount","type":"uint256"}],"name":"bondLp","outputs":[{"internalType":"uint256","name":"payout","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"bondPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bondPriceLp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"ethBondAmount","type":"uint256"},{"internalType":"uint256","name":"lpBondAmount","type":"uint256"}],"name":"create","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"depository","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"exclude","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"launch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"lpMarketInfo","outputs":[{"components":[{"internalType":"uint96","name":"capacity","type":"uint96"},{"internalType":"uint96","name":"totalDebt","type":"uint96"},{"internalType":"uint96","name":"maxPayout","type":"uint96"},{"internalType":"uint96","name":"sold","type":"uint96"},{"internalType":"uint96","name":"purchased","type":"uint96"}],"internalType":"struct PricingLibrary.Market","name":"","type":"tuple"},{"components":[{"internalType":"uint48","name":"conclusion","type":"uint48"},{"internalType":"uint256","name":"controlVariable","type":"uint256"}],"internalType":"struct PricingLibrary.Term","name":"","type":"tuple"},{"components":[{"internalType":"uint48","name":"lastTune","type":"uint48"},{"internalType":"uint48","name":"lastDecay","type":"uint48"},{"internalType":"uint48","name":"length","type":"uint48"},{"internalType":"uint48","name":"depositInterval","type":"uint48"},{"internalType":"uint48","name":"tuneInterval","type":"uint48"}],"internalType":"struct PricingLibrary.Data","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"marketInfo","outputs":[{"components":[{"internalType":"uint96","name":"capacity","type":"uint96"},{"internalType":"uint96","name":"totalDebt","type":"uint96"},{"internalType":"uint96","name":"maxPayout","type":"uint96"},{"internalType":"uint96","name":"sold","type":"uint96"},{"internalType":"uint96","name":"purchased","type":"uint96"}],"internalType":"struct PricingLibrary.Market","name":"","type":"tuple"},{"components":[{"internalType":"uint48","name":"conclusion","type":"uint48"},{"internalType":"uint256","name":"controlVariable","type":"uint256"}],"internalType":"struct PricingLibrary.Term","name":"","type":"tuple"},{"components":[{"internalType":"uint48","name":"lastTune","type":"uint48"},{"internalType":"uint48","name":"lastDecay","type":"uint48"},{"internalType":"uint48","name":"length","type":"uint48"},{"internalType":"uint48","name":"depositInterval","type":"uint48"},{"internalType":"uint48","name":"tuneInterval","type":"uint48"}],"internalType":"struct PricingLibrary.Data","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"ownership","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"payout","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"redemptionPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

61010060405234801562000011575f80fd5b50620000323073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2620001c6565b6001600160a01b031660a0819052600260209081527fd1c69375fae4db1f9bc09d344dd4ca5ec7325a49ae090b3810917b7940a06d4b8054600160ff1991821681179092557fda4acfa3de973735c764cfbaff39d0713857968d5508c62047720cdf3757d5358054821683179055305f90815260408082208054841685179055948152600384528490208054909116909117905581516318160ddd60e01b81529151620001579273946ef43867225695e29241813a8f41519634b36b9273c75c635c1f5e21d23ec8592cb37503b82a7ef942926318160ddd9260048082019392918290030181865afa1580156200012b573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620001519190620002d0565b62000226565b60a05162000165906200027f565b6001600160a01b0390811660e0521660c0819052301462000187575f6200018a565b60015b1515608052305f908152600160209081526040808320737a250d5630b4cf539739df2c5dacb4c659f2488d845290915290205f199055620002e8565b5f6040516364e329cb60e11b81526001600160a01b03841660048201526001600160a01b038316602482015260205f6044835f735c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f5af19050806200021c575f80fd5b50505f5192915050565b6001600160a01b0382165f818152602081815260408083208054860190556004805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b5f80604051630dfe168160e01b815260205f600483875afa63d21220a760e01b60048301526020806004808501885afa9150811581151715620002c0575f80fd5b50505f5191506020519050915091565b5f60208284031215620002e1575f80fd5b5051919050565b60805160a05160c05160e051612ffc620003325f395f50505f50505f81816102ab0152818161143e01528181612a2b0152612b8201525f8181612a830152612bfa0152612ffc5ff3fe608060405260043610610164575f3560e01c806364c9ec6f116100cd578063bedd12a511610087578063d926de1c11610062578063d926de1c146104bb578063db006a75146104da578063dd62ed3e146104f9578063df8980b31461053d575f80fd5b8063bedd12a51461046d578063c5b748c014610493578063d7ccfb0b146104a7575f80fd5b806364c9ec6f146103b357806370a08231146103bb5780637b16c21e146103ef57806395d89b41146104035780639f7b45791461042f578063a9059cbb1461044e575f80fd5b806323b872dd1161011e57806323b872dd1461030157806326749e8714610320578063313ce5671461033457806342966c681461034f5780634febf53d1461036e5780635d03147a1461038d575f80fd5b806301339c211461016f578063031bee001461018557806306fdde0314610239578063095ea7b31461026e57806316f0115b1461029d57806318160ddd146102e3575f80fd5b3661016b57005b5f80fd5b34801561017a575f80fd5b5061018361055c565b005b348015610190575f80fd5b5061019961060c565b6040805184516001600160601b0390811682526020808701518216818401528684015182168385015260608088015183168185015260809788015190921687840152855165ffffffffffff90811660a08501529581015160c08401528451861660e0840152840151851661010083015291830151841661012082015290820151831661014082015292015116610160820152610180015b60405180910390f35b348015610244575f80fd5b506040805180820190915260048152634b6f746f60e01b60208201525b6040516102309190612c90565b348015610279575f80fd5b5061028d610288366004612cf2565b6106f5565b6040519015158152602001610230565b3480156102a8575f80fd5b507f00000000000000000000000000000000000000000000000000000000000000005b6040516001600160a01b039091168152602001610230565b3480156102ee575f80fd5b506004545b604051908152602001610230565b34801561030c575f80fd5b5061028d61031b366004612d1a565b610722565b34801561032b575f80fd5b506101996107f6565b34801561033f575f80fd5b5060405160128152602001610230565b34801561035a575f80fd5b5061028d610369366004612d53565b6108df565b348015610379575f80fd5b50610183610388366004612d6a565b610917565b348015610398575f80fd5b5073946ef43867225695e29241813a8f41519634b36b6102cb565b6102f3610996565b3480156103c6575f80fd5b506102f36103d5366004612d6a565b6001600160a01b03165f9081526020819052604090205490565b3480156103fa575f80fd5b506102f36110ee565b34801561040e575f80fd5b506040805180820190915260048152634b4f544f60e01b6020820152610261565b34801561043a575f80fd5b50610183610449366004612d83565b6110fd565b348015610459575f80fd5b5061028d610468366004612cf2565b61120d565b348015610478575f80fd5b5073e58b33c813ac4077bd2519de90fccb189a19fa716102cb565b34801561049e575f80fd5b506102f3611254565b3480156104b2575f80fd5b506102f3611275565b3480156104c6575f80fd5b506101836104d5366004612d6a565b611280565b3480156104e5575f80fd5b506102f36104f4366004612d53565b61130d565b348015610504575f80fd5b506102f3610513366004612da3565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b348015610548575f80fd5b506102f3610557366004612d53565b611398565b3373946ef43867225695e29241813a8f41519634b36b1461059057604051635fc483c560e01b815260040160405180910390fd5b601554610100900460ff16156105b9576040516319f4db0f60e31b815260040160405180910390fd5b6105c1611b8c565b6015805461ff0019166101001790556040517feca0dfbda743d141662328d4d48393e344b2c60df0430297221df823f2926dba906106029042815260200190565b60405180910390a1565b610614612c63565b604080518082019091525f808252602082015261062f612c63565b50506040805160a080820183526007546001600160601b038082168452600160601b91829004811660208086019190915260085480831686880152839004821660608087019190915260095490921660808087019190915286518088018852600a5465ffffffffffff9081168252600b5482850152885196870189526006548082168852600160301b8104821694880194909452948304851697860197909752600160901b8204841692850192909252600160c01b900490911690820152909391925090565b335f9081526001602081815260408084206001600160a01b03871685529091529091208290555b92915050565b5f6001600160a01b0383161580610737575081155b1561075557604051632f35253160e01b815260040160405180910390fd5b6001600160a01b03841633146107e0576001600160a01b0384165f9081526001602090815260408083203384529091529020548211156107a8576040516358d246fb60e11b815260040160405180910390fd5b6001600160a01b0384165f908152600160209081526040808320338452909152812080548492906107da908490612de8565b90915550505b6107eb848484611c2d565b5060015b9392505050565b6107fe612c63565b604080518082019091525f8082526020820152610819612c63565b50506040805160a08082018352600e546001600160601b038082168452600160601b918290048116602080860191909152600f548083168688015283900482166060808701919091526010549092166080808701919091528651808801885260115465ffffffffffff90811682526012548285015288519687018952600d548082168852600160301b8104821694880194909452948304851697860197909752600160901b8204841692850192909252600160c01b900490911690820152909391925090565b5f6108ea3383611e0e565b506040518181526001905f9033905f80516020612fa78339815191529060200160405180910390a3919050565b3373946ef43867225695e29241813a8f41519634b36b1461094b57604051635fc483c560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260026020526040808220805460ff19166001179055517fec2dffa455deca3e695cce255e2b110b5ca334fb5b166f3159bbaad319ce0f1b9190a250565b6015545f9060ff166002036109be5760405163558a1e0360e11b815260040160405180910390fd5b6015805460ff19166002179055600a5465ffffffffffff164211156109f55760405162b5f6bf60e41b815260040160405180910390fd5b6007546001600160601b0316156110d4575f60076040518060a00160405290815f82015f9054906101000a90046001600160601b03166001600160601b03166001600160601b031681526020015f8201600c9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152602001600182015f9054906101000a90046001600160601b03166001600160601b03166001600160601b0316815260200160018201600c9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152602001600282015f9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152505090505f600a6040518060400160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160018201548152505090505f60066040518060a00160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160069054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201600c9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160129054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff168152505090505f60056040518060800160405290815f82015f9054906101000a90046001600160801b03166001600160801b03166001600160801b031681526020015f820160109054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160169054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201601c9054906101000a900460ff16151515158152505090505f60045490505f429050610dcb60066040518060a00160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160069054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201600c9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160129054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681525050878786611e91565b809650819850829750839950505050505f610df8866020015188602001516001600160601b031685611fb7565b905080610e0d34670de0b6b3a7640000612dfb565b610e179190612e26565b6008549098506001600160601b0316881115610e46576040516305c250cf60e11b815260040160405180910390fd5b87875f01818151610e579190612e39565b6001600160601b0316905250608087018051349190610e77908390612e60565b6001600160601b0316905250606087018051899190610e97908390612e60565b6001600160601b0316905250602087018051899190610eb7908390612e60565b6001600160601b03169052505f610ece338a611fe7565b905080610eee5760405163dde1446d60e01b815260040160405180910390fd5b604080518a81526020810184905233917f3ae9ad26d7d47616d306d7757b947fe7b0f9a7c61a5f0dc784b0ddb6c7c40b5a910160405180910390a2610f3783898989898961206b565b8351600780546020808801516001600160601b039485166001600160c01b031993841617600160601b918616820217909355604080890151600880546060808d015193891691909616179187168602919091179055608098890151600980546001600160601b0319908116929097169190911790558751600a805465ffffffffffff191665ffffffffffff92831617905597820151600b55865160068054898501518a8501518b8801519b909d01516bffffffffffffffffffffffff60601b19948d169290991691909117600160301b918c1691909102179190911699891690940265ffffffffffff60901b191698909817600160901b968816969096029590951765ffffffffffff60c01b1916600160c01b93871693909302929092179055815160058054948401519684015193909201516001600160801b039091166001600160b01b031990941693909317600160801b958516959095029490941766ffffffffffffff60b01b1916600160b01b919093160260ff60e01b191691909117600160e01b91151591909102179055506110de9650505050505050565b6110de333461226e565b6015805460ff1916600117905590565b5f6110f85f6122c5565b905090565b3373946ef43867225695e29241813a8f41519634b36b1480159061113557503373e58b33c813ac4077bd2519de90fccb189a19fa7114155b1561115357604051636edaef2f60e11b815260040160405180910390fd5b600a544265ffffffffffff9091161115611180576040516301f2595960e01b815260040160405180910390fd5b305f9081526020819052604090205480156111d457305f8181526020818152604080832080548690039055600480548690039055518481529192915f80516020612fa7833981519152910160405180910390a35b5f6111df8385612e80565b90506111ec333083610722565b50601384905560148390556111ff6123df565b611207612620565b50505050565b5f6001600160a01b0383161580611222575081155b1561124057604051632f35253160e01b815260040160405180910390fd5b61124b338484611c2d565b50600192915050565b6004545f9061126b47670de0b6b3a7640000612dfb565b6110f89190612e26565b5f6110f860016122c5565b3373946ef43867225695e29241813a8f41519634b36b146112b457604051635fc483c560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260036020908152604091829020805460ff1916600117905590519182527f10cdbb821aa416c854add806e1d7e8138afe2a538921cebe99b1351362ae38b2910160405180910390a150565b5f8061132447670de0b6b3a764000060045461286a565b90506113398184670de0b6b3a764000061286a565b91506113453384611e0e565b61134f338361226e565b604080518481526020810184905290810182905233907fbd5034ffbd47e4e72a94baa2cdb74c6fad73cb3bcdc13036b72ec8306f5a76469060600160405180910390a250919050565b6015545f9060ff166002036113c05760405163558a1e0360e11b815260040160405180910390fd5b6015805460ff1916600217905560115465ffffffffffff164211156113f75760405162b5f6bf60e41b815260040160405180910390fd5b600e546001600160601b031615611b7a576040516323b872dd60e01b815233600482015273e58b33c813ac4077bd2519de90fccb189a19fa716024820152604481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303815f875af115801561148c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114b09190612e93565b505f600e6040518060a00160405290815f82015f9054906101000a90046001600160601b03166001600160601b03166001600160601b031681526020015f8201600c9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152602001600182015f9054906101000a90046001600160601b03166001600160601b03166001600160601b0316815260200160018201600c9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152602001600282015f9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152505090505f60116040518060400160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160018201548152505090505f600d6040518060a00160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160069054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201600c9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160129054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff168152505090505f600c6040518060800160405290815f82015f9054906101000a90046001600160801b03166001600160801b03166001600160801b031681526020015f820160109054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160169054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201601c9054906101000a900460ff16151515158152505090505f60045490505f429050611876600d6040518060a00160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160069054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201600c9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160129054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681525050878786611e91565b809650819850829750839950505050505f6118a3866020015188602001516001600160601b031685611fb7565b9050806118b88a670de0b6b3a7640000612dfb565b6118c29190612e26565b600f549098506001600160601b03168811156118f1576040516305c250cf60e11b815260040160405180910390fd5b87875f018181516119029190612e39565b6001600160601b03169052506080870180518a9190611922908390612e60565b6001600160601b0316905250606087018051899190611942908390612e60565b6001600160601b0316905250602087018051899190611962908390612e60565b6001600160601b03169052505f611979338a611fe7565b9050806119995760405163dde1446d60e01b815260040160405180910390fd5b604080518a81526020810184905233917f3ae9ad26d7d47616d306d7757b947fe7b0f9a7c61a5f0dc784b0ddb6c7c40b5a910160405180910390a26119e283898989898961206b565b8351600e80546020808801516001600160601b039485166001600160c01b031993841617600160601b918616820217909355604080890151600f80546060808d015193891691909616179187168602919091179055608098890151601080546001600160601b03199081169290971691909117905587516011805465ffffffffffff191665ffffffffffff928316179055978201516012558651600d8054898501518a8501518b8801519b909d01516bffffffffffffffffffffffff60601b19948d169290991691909117600160301b918c1691909102179190911699891690940265ffffffffffff60901b191698909817600160901b968816969096029590951765ffffffffffff60c01b1916600160c01b938716939093029290921790558151600c8054948401519684015193909201516001600160801b039091166001600160b01b031990941693909317600160801b958516959095029490941766ffffffffffffff60b01b1916600160b01b919093160260ff60e01b191691909117600160e01b9115159190910217905550505050505050505b6015805460ff19166001179055919050565b5f805f306001600160a01b03166001600160a01b031681526020019081526020015f2054905060405163f305d71960e01b81526001600160a01b03301660048201528160248201525f60448201525f606482015273e58b33c813ac4077bd2519de90fccb189a19fa7160848201524260a48201525f8060c4833031737a250d5630b4cf539739df2c5dacb4c659f2488d5af1905080611c29575f80fd5b5050565b6001600160a01b0383165f90815260208190526040902054811115611c655760405163064c392760e21b815260040160405180910390fd5b6001600160a01b0382165f9081526003602052604081205460ff1680611ca257506001600160a01b0384165f9081526003602052604090205460ff165b15611cf4576001600160a01b0383165f9081526002602052604090205460ff1680611ce457506001600160a01b0384165f9081526002602052604090205460ff165b15611cf057505f611cf4565b5060015b8015611da1575f6103e8611d09603285612dfb565b611d139190612e26565b6001600160a01b0386165f9081526020819052604081208054869003905573e58b33c813ac4077bd2519de90fccb189a19fa7190527f1338836141591a3221ceb363e91a05d18b16e6fa044cb293d015e6c316402dc78054820190559050611d7b8184612de8565b6001600160a01b0385165f9081526020819052604090208054820190559250611dce9050565b6001600160a01b038085165f90815260208190526040808220805486900390559185168152208054830190555b826001600160a01b0316846001600160a01b03165f80516020612fa783398151915284604051611e0091815260200190565b60405180910390a350505050565b6001600160a01b0382165f90815260208190526040902054811115611e465760405163064c392760e21b815260040160405180910390fd5b6001600160a01b0382165f8181526020818152604080832080548690039055600480548690039055518481529192915f80516020612fa7833981519152910160405180910390a35050565b611e99612c63565b611ea1612c63565b6040805180820182525f8082526020808301829052835160808101855282815290810182905292830181905260608301529042611ede8989612914565b67ffffffffffffffff1688602001818151611ef99190612e39565b6001600160601b031690525065ffffffffffff811660208a0152606086015115611fa9575f805f611f2989612956565b925092509250826001600160801b03168a602001818151611f4a9190612de8565b9052508015611f9e5782895f01818151611f649190612eb2565b6001600160801b0316905250604089018051839190611f84908390612ed2565b65ffffffffffff908116909152851660208b015250611fa5565b5f60608a01525b5050505b509597949550929392505050565b5f670de0b6b3a7640000611fcb84846129e7565b611fd59086612dfb565b611fdf9190612e26565b949350505050565b305f9081526020819052604081205482111561201657604051635e36b3df60e01b815260040160405180910390fd5b506001600160a01b0382165f818152602081815260408083208054860190553080845292819020805486900390555184815260019392915f80516020612fa7833981519152910160405180910390a392915050565b612073612c63565b604080518082019091525f808252602082015261208e612c63565b604080516080810182525f8082526020820181905291810182905260608101919091526120de6040518060a001604052805f81526020015f81526020015f81526020015f81526020015f81525090565b608088015188516120ef9190612ef1565b65ffffffffffff168b65ffffffffffff161061225c578851612112908c90612ed2565b65ffffffffffff1681526020808a0151908b015161213a91906001600160601b031688611fb7565b602082015289516001600160601b031660408201819052815160608a0151909161216c9165ffffffffffff1690612dfb565b6121769190612e26565b6001600160601b03166040808c01919091528151898201519183015190916121a89165ffffffffffff90911690612dfb565b6121b29190612e26565b6060820181905260208201516121c9908890612dfb565b6121d39190612e26565b6080820181905260208a01511115612245575f81608001518a602001516121fa9190612de8565b90506040518060800160405280826001600160801b031681526020018d65ffffffffffff1681526020018a6080015165ffffffffffff16815260200160011515815250975050612250565b608081015160208a01525b65ffffffffffff8b1688525b50979996985094965092949350505050565b5f805f805f85875af19050806122c05760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b604482015260640160405180910390fd5b505050565b5f811561235a57600b54604080516080810182526005546001600160801b0381168252600160801b810465ffffffffffff9081166020840152600160b01b82041692820192909252600160e01b90910460ff161515606082015261071c9161232c91612a05565b60075460045461234c91600160601b90046001600160601b0316906129e7565b670de0b6b3a764000061286a565b60125460408051608081018252600c546001600160801b0381168252600160801b810465ffffffffffff9081166020840152600160b01b82041692820192909252600160e01b90910460ff161515606082015261071c916123ba91612a05565b600e5460045461234c91600160601b90046001600160601b0316906129e7565b919050565b6013548015612619575f6123f1612a27565b9050815f62093a806124068362015180612f10565b6001600160601b03166124199190612e26565b90505f846001600160601b0316600454856124349190612dfb565b61243e9190612e26565b90505f612454846001600160601b031686612b01565b90505f61246462093a8042612e80565b905081156125c3576040805160a080820183526001600160601b038881168084528b82166020808601829052928a168587018190525f6060808801829052608097880191909152600780546001600160c01b03199081168617600160601b90950294909417905560088054909316909117909155600980546001600160601b03199081169091558651808801885265ffffffffffff8981168083529186018c9052600a805465ffffffffffff191683179055600b8c9055885196870189524290811680885287870181905262093a80888b015262015180888601526107089790980196909652600680549092168717600160301b90970296909617600160601b600160f01b0319166c0e1000000002a300000000127560671b179055855191825291810192909252928101919091527f035d6743050a54c5c545b7f45bddbd082bf97e098d81e6eb10045ab6a10ab510910160405180910390a1612612565b6125d630866001600160601b0316611e0e565b6125e362093a8042612e80565b600a805465ffffffffffff191665ffffffffffff92909216919091179055600780546001600160601b03191690555b5050505050505b505f601355565b6014546001600160601b03811615612863575f61263b612b7e565b9050815f62093a806126508362015180612f10565b6001600160601b03166126639190612e26565b90505f846001600160601b03166004548561267e9190612dfb565b6126889190612e26565b90505f61269e846001600160601b031686612b01565b90505f6126ae62093a8042612e80565b9050811561280d576040805160a080820183526001600160601b038881168084528b82166020808601829052928a168587018190525f6060808801829052608097880191909152600e80546001600160c01b03199081168617600160601b909502949094179055600f8054909316909117909155601080546001600160601b03199081169091558651808801885265ffffffffffff8981168083529186018c90526011805465ffffffffffff19168317905560128c9055885196870189524290811680885287870181905262093a80888b015262015180888601526107089790980196909652600d80549092168717600160301b90970296909617600160601b600160f01b0319166c0e1000000002a300000000127560671b179055855191825291810192909252928101919091527f035d6743050a54c5c545b7f45bddbd082bf97e098d81e6eb10045ab6a10ab510910160405180910390a161285c565b61282030866001600160601b0316611e0e565b61282d62093a8042612e80565b6011805465ffffffffffff191665ffffffffffff92909216919091179055600e80546001600160601b03191690555b5050505050505b505f601455565b5f80805f19858709858702925082811083820303915050805f0361289e575f8411612893575f80fd5b5082900490506107ef565b8084116128a9575f80fd5b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b5f80836020015165ffffffffffff164261292e9190612de8565b9050836040015165ffffffffffff168184602001516001600160601b0316611fd59190612dfb565b5f805f836060015161296f57505f9150819050806129e0565b5f8460200151426129809190612ed2565b90505f856040015165ffffffffffff168265ffffffffffff161090505f816129a95786516129d7565b866040015165ffffffffffff168365ffffffffffff16885f01516129cd9190612f3b565b6129d79190612f5e565b95509193509150505b9193909250565b5f816129fb84670de0b6b3a7640000612dfb565b6107ef9190612e26565b5f80612a1083612956565b50506001600160801b03169050611fdf8185612de8565b5f807f000000000000000000000000000000000000000000000000000000000000000090505f80604051630240bc6b60e21b81525f80600483875afa905080612a6e575f80fd5b5060205f803e60208060203e50505f516020517f000000000000000000000000000000000000000000000000000000000000000015612ad357612acc816001600160701b0316670de0b6b3a7640000846001600160701b031661286a565b9350612afb565b612af8826001600160701b0316670de0b6b3a7640000836001600160701b031661286a565b93505b50505090565b6004545f9081612b118583612de8565b612b2347670de0b6b3a7640000612dfb565b612b2d9190612e26565b90505f82612b3b8688612dfb565b612b4d47670de0b6b3a7640000612dfb565b612b579190612e80565b612b619190612e26565b905080821015612b72576001612b74565b5f5b9695505050505050565b5f807f000000000000000000000000000000000000000000000000000000000000000090505f805f604051630240bc6b60e21b81525f80600483885afa80612bc4575f80fd5b5060205f803e60208060203e5f51935060205192506318160ddd60e01b602082015260205f600460208401885afa50505f5190507f000000000000000000000000000000000000000000000000000000000000000015612c4b57612c44612c2c846002612f83565b6001600160701b0316670de0b6b3a76400008361286a565b9450612c5c565b612c59612c2c836002612f83565b94505b5050505090565b6040805160a0810182525f8082526020820181905291810182905260608101829052608081019190915290565b5f602080835283518060208501525f5b81811015612cbc57858101830151858201604001528201612ca0565b505f604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b03811681146123da575f80fd5b5f8060408385031215612d03575f80fd5b612d0c83612cdc565b946020939093013593505050565b5f805f60608486031215612d2c575f80fd5b612d3584612cdc565b9250612d4360208501612cdc565b9150604084013590509250925092565b5f60208284031215612d63575f80fd5b5035919050565b5f60208284031215612d7a575f80fd5b6107ef82612cdc565b5f8060408385031215612d94575f80fd5b50508035926020909101359150565b5f8060408385031215612db4575f80fd5b612dbd83612cdc565b9150612dcb60208401612cdc565b90509250929050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561071c5761071c612dd4565b808202811582820484141761071c5761071c612dd4565b634e487b7160e01b5f52601260045260245ffd5b5f82612e3457612e34612e12565b500490565b6001600160601b03828116828216039080821115612e5957612e59612dd4565b5092915050565b6001600160601b03818116838216019080821115612e5957612e59612dd4565b8082018082111561071c5761071c612dd4565b5f60208284031215612ea3575f80fd5b815180151581146107ef575f80fd5b6001600160801b03828116828216039080821115612e5957612e59612dd4565b65ffffffffffff828116828216039080821115612e5957612e59612dd4565b65ffffffffffff818116838216019080821115612e5957612e59612dd4565b6001600160601b03818116838216028082169190828114612f3357612f33612dd4565b505092915050565b6001600160801b03818116838216028082169190828114612f3357612f33612dd4565b5f6001600160801b0380841680612f7757612f77612e12565b92169190910492915050565b6001600160701b03818116838216028082169190828114612f3357612f33612dd456feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220caf4e3b4220f06c011dec8269de8b0005be17a0e02575fba2b57079b228073c064736f6c63430008170033

Deployed Bytecode

0x608060405260043610610164575f3560e01c806364c9ec6f116100cd578063bedd12a511610087578063d926de1c11610062578063d926de1c146104bb578063db006a75146104da578063dd62ed3e146104f9578063df8980b31461053d575f80fd5b8063bedd12a51461046d578063c5b748c014610493578063d7ccfb0b146104a7575f80fd5b806364c9ec6f146103b357806370a08231146103bb5780637b16c21e146103ef57806395d89b41146104035780639f7b45791461042f578063a9059cbb1461044e575f80fd5b806323b872dd1161011e57806323b872dd1461030157806326749e8714610320578063313ce5671461033457806342966c681461034f5780634febf53d1461036e5780635d03147a1461038d575f80fd5b806301339c211461016f578063031bee001461018557806306fdde0314610239578063095ea7b31461026e57806316f0115b1461029d57806318160ddd146102e3575f80fd5b3661016b57005b5f80fd5b34801561017a575f80fd5b5061018361055c565b005b348015610190575f80fd5b5061019961060c565b6040805184516001600160601b0390811682526020808701518216818401528684015182168385015260608088015183168185015260809788015190921687840152855165ffffffffffff90811660a08501529581015160c08401528451861660e0840152840151851661010083015291830151841661012082015290820151831661014082015292015116610160820152610180015b60405180910390f35b348015610244575f80fd5b506040805180820190915260048152634b6f746f60e01b60208201525b6040516102309190612c90565b348015610279575f80fd5b5061028d610288366004612cf2565b6106f5565b6040519015158152602001610230565b3480156102a8575f80fd5b507f00000000000000000000000047287d8d7c1a5854aa11868e7d2186b138069f845b6040516001600160a01b039091168152602001610230565b3480156102ee575f80fd5b506004545b604051908152602001610230565b34801561030c575f80fd5b5061028d61031b366004612d1a565b610722565b34801561032b575f80fd5b506101996107f6565b34801561033f575f80fd5b5060405160128152602001610230565b34801561035a575f80fd5b5061028d610369366004612d53565b6108df565b348015610379575f80fd5b50610183610388366004612d6a565b610917565b348015610398575f80fd5b5073946ef43867225695e29241813a8f41519634b36b6102cb565b6102f3610996565b3480156103c6575f80fd5b506102f36103d5366004612d6a565b6001600160a01b03165f9081526020819052604090205490565b3480156103fa575f80fd5b506102f36110ee565b34801561040e575f80fd5b506040805180820190915260048152634b4f544f60e01b6020820152610261565b34801561043a575f80fd5b50610183610449366004612d83565b6110fd565b348015610459575f80fd5b5061028d610468366004612cf2565b61120d565b348015610478575f80fd5b5073e58b33c813ac4077bd2519de90fccb189a19fa716102cb565b34801561049e575f80fd5b506102f3611254565b3480156104b2575f80fd5b506102f3611275565b3480156104c6575f80fd5b506101836104d5366004612d6a565b611280565b3480156104e5575f80fd5b506102f36104f4366004612d53565b61130d565b348015610504575f80fd5b506102f3610513366004612da3565b6001600160a01b039182165f90815260016020908152604080832093909416825291909152205490565b348015610548575f80fd5b506102f3610557366004612d53565b611398565b3373946ef43867225695e29241813a8f41519634b36b1461059057604051635fc483c560e01b815260040160405180910390fd5b601554610100900460ff16156105b9576040516319f4db0f60e31b815260040160405180910390fd5b6105c1611b8c565b6015805461ff0019166101001790556040517feca0dfbda743d141662328d4d48393e344b2c60df0430297221df823f2926dba906106029042815260200190565b60405180910390a1565b610614612c63565b604080518082019091525f808252602082015261062f612c63565b50506040805160a080820183526007546001600160601b038082168452600160601b91829004811660208086019190915260085480831686880152839004821660608087019190915260095490921660808087019190915286518088018852600a5465ffffffffffff9081168252600b5482850152885196870189526006548082168852600160301b8104821694880194909452948304851697860197909752600160901b8204841692850192909252600160c01b900490911690820152909391925090565b335f9081526001602081815260408084206001600160a01b03871685529091529091208290555b92915050565b5f6001600160a01b0383161580610737575081155b1561075557604051632f35253160e01b815260040160405180910390fd5b6001600160a01b03841633146107e0576001600160a01b0384165f9081526001602090815260408083203384529091529020548211156107a8576040516358d246fb60e11b815260040160405180910390fd5b6001600160a01b0384165f908152600160209081526040808320338452909152812080548492906107da908490612de8565b90915550505b6107eb848484611c2d565b5060015b9392505050565b6107fe612c63565b604080518082019091525f8082526020820152610819612c63565b50506040805160a08082018352600e546001600160601b038082168452600160601b918290048116602080860191909152600f548083168688015283900482166060808701919091526010549092166080808701919091528651808801885260115465ffffffffffff90811682526012548285015288519687018952600d548082168852600160301b8104821694880194909452948304851697860197909752600160901b8204841692850192909252600160c01b900490911690820152909391925090565b5f6108ea3383611e0e565b506040518181526001905f9033905f80516020612fa78339815191529060200160405180910390a3919050565b3373946ef43867225695e29241813a8f41519634b36b1461094b57604051635fc483c560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260026020526040808220805460ff19166001179055517fec2dffa455deca3e695cce255e2b110b5ca334fb5b166f3159bbaad319ce0f1b9190a250565b6015545f9060ff166002036109be5760405163558a1e0360e11b815260040160405180910390fd5b6015805460ff19166002179055600a5465ffffffffffff164211156109f55760405162b5f6bf60e41b815260040160405180910390fd5b6007546001600160601b0316156110d4575f60076040518060a00160405290815f82015f9054906101000a90046001600160601b03166001600160601b03166001600160601b031681526020015f8201600c9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152602001600182015f9054906101000a90046001600160601b03166001600160601b03166001600160601b0316815260200160018201600c9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152602001600282015f9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152505090505f600a6040518060400160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160018201548152505090505f60066040518060a00160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160069054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201600c9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160129054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff168152505090505f60056040518060800160405290815f82015f9054906101000a90046001600160801b03166001600160801b03166001600160801b031681526020015f820160109054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160169054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201601c9054906101000a900460ff16151515158152505090505f60045490505f429050610dcb60066040518060a00160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160069054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201600c9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160129054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681525050878786611e91565b809650819850829750839950505050505f610df8866020015188602001516001600160601b031685611fb7565b905080610e0d34670de0b6b3a7640000612dfb565b610e179190612e26565b6008549098506001600160601b0316881115610e46576040516305c250cf60e11b815260040160405180910390fd5b87875f01818151610e579190612e39565b6001600160601b0316905250608087018051349190610e77908390612e60565b6001600160601b0316905250606087018051899190610e97908390612e60565b6001600160601b0316905250602087018051899190610eb7908390612e60565b6001600160601b03169052505f610ece338a611fe7565b905080610eee5760405163dde1446d60e01b815260040160405180910390fd5b604080518a81526020810184905233917f3ae9ad26d7d47616d306d7757b947fe7b0f9a7c61a5f0dc784b0ddb6c7c40b5a910160405180910390a2610f3783898989898961206b565b8351600780546020808801516001600160601b039485166001600160c01b031993841617600160601b918616820217909355604080890151600880546060808d015193891691909616179187168602919091179055608098890151600980546001600160601b0319908116929097169190911790558751600a805465ffffffffffff191665ffffffffffff92831617905597820151600b55865160068054898501518a8501518b8801519b909d01516bffffffffffffffffffffffff60601b19948d169290991691909117600160301b918c1691909102179190911699891690940265ffffffffffff60901b191698909817600160901b968816969096029590951765ffffffffffff60c01b1916600160c01b93871693909302929092179055815160058054948401519684015193909201516001600160801b039091166001600160b01b031990941693909317600160801b958516959095029490941766ffffffffffffff60b01b1916600160b01b919093160260ff60e01b191691909117600160e01b91151591909102179055506110de9650505050505050565b6110de333461226e565b6015805460ff1916600117905590565b5f6110f85f6122c5565b905090565b3373946ef43867225695e29241813a8f41519634b36b1480159061113557503373e58b33c813ac4077bd2519de90fccb189a19fa7114155b1561115357604051636edaef2f60e11b815260040160405180910390fd5b600a544265ffffffffffff9091161115611180576040516301f2595960e01b815260040160405180910390fd5b305f9081526020819052604090205480156111d457305f8181526020818152604080832080548690039055600480548690039055518481529192915f80516020612fa7833981519152910160405180910390a35b5f6111df8385612e80565b90506111ec333083610722565b50601384905560148390556111ff6123df565b611207612620565b50505050565b5f6001600160a01b0383161580611222575081155b1561124057604051632f35253160e01b815260040160405180910390fd5b61124b338484611c2d565b50600192915050565b6004545f9061126b47670de0b6b3a7640000612dfb565b6110f89190612e26565b5f6110f860016122c5565b3373946ef43867225695e29241813a8f41519634b36b146112b457604051635fc483c560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260036020908152604091829020805460ff1916600117905590519182527f10cdbb821aa416c854add806e1d7e8138afe2a538921cebe99b1351362ae38b2910160405180910390a150565b5f8061132447670de0b6b3a764000060045461286a565b90506113398184670de0b6b3a764000061286a565b91506113453384611e0e565b61134f338361226e565b604080518481526020810184905290810182905233907fbd5034ffbd47e4e72a94baa2cdb74c6fad73cb3bcdc13036b72ec8306f5a76469060600160405180910390a250919050565b6015545f9060ff166002036113c05760405163558a1e0360e11b815260040160405180910390fd5b6015805460ff1916600217905560115465ffffffffffff164211156113f75760405162b5f6bf60e41b815260040160405180910390fd5b600e546001600160601b031615611b7a576040516323b872dd60e01b815233600482015273e58b33c813ac4077bd2519de90fccb189a19fa716024820152604481018390527f00000000000000000000000047287d8d7c1a5854aa11868e7d2186b138069f846001600160a01b0316906323b872dd906064016020604051808303815f875af115801561148c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114b09190612e93565b505f600e6040518060a00160405290815f82015f9054906101000a90046001600160601b03166001600160601b03166001600160601b031681526020015f8201600c9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152602001600182015f9054906101000a90046001600160601b03166001600160601b03166001600160601b0316815260200160018201600c9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152602001600282015f9054906101000a90046001600160601b03166001600160601b03166001600160601b03168152505090505f60116040518060400160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff16815260200160018201548152505090505f600d6040518060a00160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160069054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201600c9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160129054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff168152505090505f600c6040518060800160405290815f82015f9054906101000a90046001600160801b03166001600160801b03166001600160801b031681526020015f820160109054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160169054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201601c9054906101000a900460ff16151515158152505090505f60045490505f429050611876600d6040518060a00160405290815f82015f9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160069054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f8201600c9054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160129054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681526020015f820160189054906101000a900465ffffffffffff1665ffffffffffff1665ffffffffffff1681525050878786611e91565b809650819850829750839950505050505f6118a3866020015188602001516001600160601b031685611fb7565b9050806118b88a670de0b6b3a7640000612dfb565b6118c29190612e26565b600f549098506001600160601b03168811156118f1576040516305c250cf60e11b815260040160405180910390fd5b87875f018181516119029190612e39565b6001600160601b03169052506080870180518a9190611922908390612e60565b6001600160601b0316905250606087018051899190611942908390612e60565b6001600160601b0316905250602087018051899190611962908390612e60565b6001600160601b03169052505f611979338a611fe7565b9050806119995760405163dde1446d60e01b815260040160405180910390fd5b604080518a81526020810184905233917f3ae9ad26d7d47616d306d7757b947fe7b0f9a7c61a5f0dc784b0ddb6c7c40b5a910160405180910390a26119e283898989898961206b565b8351600e80546020808801516001600160601b039485166001600160c01b031993841617600160601b918616820217909355604080890151600f80546060808d015193891691909616179187168602919091179055608098890151601080546001600160601b03199081169290971691909117905587516011805465ffffffffffff191665ffffffffffff928316179055978201516012558651600d8054898501518a8501518b8801519b909d01516bffffffffffffffffffffffff60601b19948d169290991691909117600160301b918c1691909102179190911699891690940265ffffffffffff60901b191698909817600160901b968816969096029590951765ffffffffffff60c01b1916600160c01b938716939093029290921790558151600c8054948401519684015193909201516001600160801b039091166001600160b01b031990941693909317600160801b958516959095029490941766ffffffffffffff60b01b1916600160b01b919093160260ff60e01b191691909117600160e01b9115159190910217905550505050505050505b6015805460ff19166001179055919050565b5f805f306001600160a01b03166001600160a01b031681526020019081526020015f2054905060405163f305d71960e01b81526001600160a01b03301660048201528160248201525f60448201525f606482015273e58b33c813ac4077bd2519de90fccb189a19fa7160848201524260a48201525f8060c4833031737a250d5630b4cf539739df2c5dacb4c659f2488d5af1905080611c29575f80fd5b5050565b6001600160a01b0383165f90815260208190526040902054811115611c655760405163064c392760e21b815260040160405180910390fd5b6001600160a01b0382165f9081526003602052604081205460ff1680611ca257506001600160a01b0384165f9081526003602052604090205460ff165b15611cf4576001600160a01b0383165f9081526002602052604090205460ff1680611ce457506001600160a01b0384165f9081526002602052604090205460ff165b15611cf057505f611cf4565b5060015b8015611da1575f6103e8611d09603285612dfb565b611d139190612e26565b6001600160a01b0386165f9081526020819052604081208054869003905573e58b33c813ac4077bd2519de90fccb189a19fa7190527f1338836141591a3221ceb363e91a05d18b16e6fa044cb293d015e6c316402dc78054820190559050611d7b8184612de8565b6001600160a01b0385165f9081526020819052604090208054820190559250611dce9050565b6001600160a01b038085165f90815260208190526040808220805486900390559185168152208054830190555b826001600160a01b0316846001600160a01b03165f80516020612fa783398151915284604051611e0091815260200190565b60405180910390a350505050565b6001600160a01b0382165f90815260208190526040902054811115611e465760405163064c392760e21b815260040160405180910390fd5b6001600160a01b0382165f8181526020818152604080832080548690039055600480548690039055518481529192915f80516020612fa7833981519152910160405180910390a35050565b611e99612c63565b611ea1612c63565b6040805180820182525f8082526020808301829052835160808101855282815290810182905292830181905260608301529042611ede8989612914565b67ffffffffffffffff1688602001818151611ef99190612e39565b6001600160601b031690525065ffffffffffff811660208a0152606086015115611fa9575f805f611f2989612956565b925092509250826001600160801b03168a602001818151611f4a9190612de8565b9052508015611f9e5782895f01818151611f649190612eb2565b6001600160801b0316905250604089018051839190611f84908390612ed2565b65ffffffffffff908116909152851660208b015250611fa5565b5f60608a01525b5050505b509597949550929392505050565b5f670de0b6b3a7640000611fcb84846129e7565b611fd59086612dfb565b611fdf9190612e26565b949350505050565b305f9081526020819052604081205482111561201657604051635e36b3df60e01b815260040160405180910390fd5b506001600160a01b0382165f818152602081815260408083208054860190553080845292819020805486900390555184815260019392915f80516020612fa7833981519152910160405180910390a392915050565b612073612c63565b604080518082019091525f808252602082015261208e612c63565b604080516080810182525f8082526020820181905291810182905260608101919091526120de6040518060a001604052805f81526020015f81526020015f81526020015f81526020015f81525090565b608088015188516120ef9190612ef1565b65ffffffffffff168b65ffffffffffff161061225c578851612112908c90612ed2565b65ffffffffffff1681526020808a0151908b015161213a91906001600160601b031688611fb7565b602082015289516001600160601b031660408201819052815160608a0151909161216c9165ffffffffffff1690612dfb565b6121769190612e26565b6001600160601b03166040808c01919091528151898201519183015190916121a89165ffffffffffff90911690612dfb565b6121b29190612e26565b6060820181905260208201516121c9908890612dfb565b6121d39190612e26565b6080820181905260208a01511115612245575f81608001518a602001516121fa9190612de8565b90506040518060800160405280826001600160801b031681526020018d65ffffffffffff1681526020018a6080015165ffffffffffff16815260200160011515815250975050612250565b608081015160208a01525b65ffffffffffff8b1688525b50979996985094965092949350505050565b5f805f805f85875af19050806122c05760405162461bcd60e51b815260206004820152601360248201527211551217d514905394d1915497d19052531151606a1b604482015260640160405180910390fd5b505050565b5f811561235a57600b54604080516080810182526005546001600160801b0381168252600160801b810465ffffffffffff9081166020840152600160b01b82041692820192909252600160e01b90910460ff161515606082015261071c9161232c91612a05565b60075460045461234c91600160601b90046001600160601b0316906129e7565b670de0b6b3a764000061286a565b60125460408051608081018252600c546001600160801b0381168252600160801b810465ffffffffffff9081166020840152600160b01b82041692820192909252600160e01b90910460ff161515606082015261071c916123ba91612a05565b600e5460045461234c91600160601b90046001600160601b0316906129e7565b919050565b6013548015612619575f6123f1612a27565b9050815f62093a806124068362015180612f10565b6001600160601b03166124199190612e26565b90505f846001600160601b0316600454856124349190612dfb565b61243e9190612e26565b90505f612454846001600160601b031686612b01565b90505f61246462093a8042612e80565b905081156125c3576040805160a080820183526001600160601b038881168084528b82166020808601829052928a168587018190525f6060808801829052608097880191909152600780546001600160c01b03199081168617600160601b90950294909417905560088054909316909117909155600980546001600160601b03199081169091558651808801885265ffffffffffff8981168083529186018c9052600a805465ffffffffffff191683179055600b8c9055885196870189524290811680885287870181905262093a80888b015262015180888601526107089790980196909652600680549092168717600160301b90970296909617600160601b600160f01b0319166c0e1000000002a300000000127560671b179055855191825291810192909252928101919091527f035d6743050a54c5c545b7f45bddbd082bf97e098d81e6eb10045ab6a10ab510910160405180910390a1612612565b6125d630866001600160601b0316611e0e565b6125e362093a8042612e80565b600a805465ffffffffffff191665ffffffffffff92909216919091179055600780546001600160601b03191690555b5050505050505b505f601355565b6014546001600160601b03811615612863575f61263b612b7e565b9050815f62093a806126508362015180612f10565b6001600160601b03166126639190612e26565b90505f846001600160601b03166004548561267e9190612dfb565b6126889190612e26565b90505f61269e846001600160601b031686612b01565b90505f6126ae62093a8042612e80565b9050811561280d576040805160a080820183526001600160601b038881168084528b82166020808601829052928a168587018190525f6060808801829052608097880191909152600e80546001600160c01b03199081168617600160601b909502949094179055600f8054909316909117909155601080546001600160601b03199081169091558651808801885265ffffffffffff8981168083529186018c90526011805465ffffffffffff19168317905560128c9055885196870189524290811680885287870181905262093a80888b015262015180888601526107089790980196909652600d80549092168717600160301b90970296909617600160601b600160f01b0319166c0e1000000002a300000000127560671b179055855191825291810192909252928101919091527f035d6743050a54c5c545b7f45bddbd082bf97e098d81e6eb10045ab6a10ab510910160405180910390a161285c565b61282030866001600160601b0316611e0e565b61282d62093a8042612e80565b6011805465ffffffffffff191665ffffffffffff92909216919091179055600e80546001600160601b03191690555b5050505050505b505f601455565b5f80805f19858709858702925082811083820303915050805f0361289e575f8411612893575f80fd5b5082900490506107ef565b8084116128a9575f80fd5b5f848688095f868103871696879004966002600389028118808a02820302808a02820302808a02820302808a02820302808a02820302808a02909103029181900381900460010186841190950394909402919094039290920491909117919091029150509392505050565b5f80836020015165ffffffffffff164261292e9190612de8565b9050836040015165ffffffffffff168184602001516001600160601b0316611fd59190612dfb565b5f805f836060015161296f57505f9150819050806129e0565b5f8460200151426129809190612ed2565b90505f856040015165ffffffffffff168265ffffffffffff161090505f816129a95786516129d7565b866040015165ffffffffffff168365ffffffffffff16885f01516129cd9190612f3b565b6129d79190612f5e565b95509193509150505b9193909250565b5f816129fb84670de0b6b3a7640000612dfb565b6107ef9190612e26565b5f80612a1083612956565b50506001600160801b03169050611fdf8185612de8565b5f807f00000000000000000000000047287d8d7c1a5854aa11868e7d2186b138069f8490505f80604051630240bc6b60e21b81525f80600483875afa905080612a6e575f80fd5b5060205f803e60208060203e50505f516020517f000000000000000000000000000000000000000000000000000000000000000115612ad357612acc816001600160701b0316670de0b6b3a7640000846001600160701b031661286a565b9350612afb565b612af8826001600160701b0316670de0b6b3a7640000836001600160701b031661286a565b93505b50505090565b6004545f9081612b118583612de8565b612b2347670de0b6b3a7640000612dfb565b612b2d9190612e26565b90505f82612b3b8688612dfb565b612b4d47670de0b6b3a7640000612dfb565b612b579190612e80565b612b619190612e26565b905080821015612b72576001612b74565b5f5b9695505050505050565b5f807f00000000000000000000000047287d8d7c1a5854aa11868e7d2186b138069f8490505f805f604051630240bc6b60e21b81525f80600483885afa80612bc4575f80fd5b5060205f803e60208060203e5f51935060205192506318160ddd60e01b602082015260205f600460208401885afa50505f5190507f000000000000000000000000000000000000000000000000000000000000000115612c4b57612c44612c2c846002612f83565b6001600160701b0316670de0b6b3a76400008361286a565b9450612c5c565b612c59612c2c836002612f83565b94505b5050505090565b6040805160a0810182525f8082526020820181905291810182905260608101829052608081019190915290565b5f602080835283518060208501525f5b81811015612cbc57858101830151858201604001528201612ca0565b505f604082860101526040601f19601f8301168501019250505092915050565b80356001600160a01b03811681146123da575f80fd5b5f8060408385031215612d03575f80fd5b612d0c83612cdc565b946020939093013593505050565b5f805f60608486031215612d2c575f80fd5b612d3584612cdc565b9250612d4360208501612cdc565b9150604084013590509250925092565b5f60208284031215612d63575f80fd5b5035919050565b5f60208284031215612d7a575f80fd5b6107ef82612cdc565b5f8060408385031215612d94575f80fd5b50508035926020909101359150565b5f8060408385031215612db4575f80fd5b612dbd83612cdc565b9150612dcb60208401612cdc565b90509250929050565b634e487b7160e01b5f52601160045260245ffd5b8181038181111561071c5761071c612dd4565b808202811582820484141761071c5761071c612dd4565b634e487b7160e01b5f52601260045260245ffd5b5f82612e3457612e34612e12565b500490565b6001600160601b03828116828216039080821115612e5957612e59612dd4565b5092915050565b6001600160601b03818116838216019080821115612e5957612e59612dd4565b8082018082111561071c5761071c612dd4565b5f60208284031215612ea3575f80fd5b815180151581146107ef575f80fd5b6001600160801b03828116828216039080821115612e5957612e59612dd4565b65ffffffffffff828116828216039080821115612e5957612e59612dd4565b65ffffffffffff818116838216019080821115612e5957612e59612dd4565b6001600160601b03818116838216028082169190828114612f3357612f33612dd4565b505092915050565b6001600160801b03818116838216028082169190828114612f3357612f33612dd4565b5f6001600160801b0380841680612f7757612f77612e12565b92169190910492915050565b6001600160701b03818116838216028082169190828114612f3357612f33612dd456feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220caf4e3b4220f06c011dec8269de8b0005be17a0e02575fba2b57079b228073c064736f6c63430008170033

Deployed Bytecode Sourcemap

936:25720:2:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12742:232;;;;;;;;;;;;;:::i;:::-;;11438:203;;;;;;;;;;;;;:::i;:::-;;;;420:13:7;;-1:-1:-1;;;;;416:22:7;;;398:41;;499:4;487:17;;;481:24;477:33;;455:20;;;448:63;559:17;;;553:24;549:33;;527:20;;;520:63;643:4;631:17;;;625:24;621:33;;599:20;;;592:63;715:4;703:17;;;697:24;693:33;;;671:20;;;664:63;801:13;;746:14;797:22;;;791:3;776:19;;769:51;863:17;;;857:24;851:3;836:19;;829:53;923:13;;919:22;;913:3;898:19;;891:51;989:17;;983:24;979:33;;973:3;958:19;;951:62;1060:17;;;1054:24;1050:33;;1044:3;1029:19;;1022:62;1131:17;;;1125:24;1121:33;;1115:3;1100:19;;1093:62;1202:17;;1196:24;1192:33;1186:3;1171:19;;1164:62;340:3;325:19;11438:203:2;;;;;;;;9532:80;;;;;;;;;;-1:-1:-1;9601:4:2;;;;;;;;;;;;-1:-1:-1;;;9601:4:2;;;;9532:80;;;;;;;:::i;4350:192::-;;;;;;;;;;-1:-1:-1;4350:192:2;;;;;:::i;:::-;;:::i;:::-;;;2392:14:7;;2385:22;2367:41;;2355:2;2340:18;4350:192:2;2227:187:7;10637:76:2;;;;;;;;;;-1:-1:-1;10702:4:2;10637:76;;;-1:-1:-1;;;;;2583:32:7;;;2565:51;;2553:2;2538:18;10637:76:2;2419:203:7;9913:89:2;;;;;;;;;;-1:-1:-1;9983:12:2;;9913:89;;;2773:25:7;;;2761:2;2746:18;9913:89:2;2627:177:7;3922:422:2;;;;;;;;;;-1:-1:-1;3922:422:2;;;;;:::i;:::-;;:::i;11647:211::-;;;;;;;;;;;;;:::i;9784:80::-;;;;;;;;;;-1:-1:-1;9784:80:2;;2093:2;3284:36:7;;3272:2;3257:18;9784:80:2;3142:184:7;9230:183:2;;;;;;;;;;-1:-1:-1;9230:183:2;;;;;:::i;:::-;;:::i;12249:165::-;;;;;;;;;;-1:-1:-1;12249:165:2;;;;;:::i;:::-;;:::i;10884:82::-;;;;;;;;;;-1:-1:-1;2520:42:2;10884:82;;4726:1896;;;:::i;10118:106::-;;;;;;;;;;-1:-1:-1;10118:106:2;;;;;:::i;:::-;-1:-1:-1;;;;;10200:17:2;10174:7;10200:17;;;;;;;;;;;;10118:106;11120:105;;;;;;;;;;;;;:::i;9655:84::-;;;;;;;;;;-1:-1:-1;9726:6:2;;;;;;;;;;;;-1:-1:-1;;;9726:6:2;;;;9655:84;;13236:991;;;;;;;;;;-1:-1:-1;13236:991:2;;;;;:::i;:::-;;:::i;3695:221::-;;;;;;;;;;-1:-1:-1;3695:221:2;;;;;:::i;:::-;;:::i;11864:93::-;;;;;;;;;;-1:-1:-1;2611:42:2;11864:93;;11302:130;;;;;;;;;;;;;:::i;11012:102::-;;;;;;;;;;;;;:::i;12515:159::-;;;;;;;;;;-1:-1:-1;12515:159:2;;;;;:::i;:::-;;:::i;8719:405::-;;;;;;;;;;-1:-1:-1;8719:405:2;;;;;:::i;:::-;;:::i;10441:140::-;;;;;;;;;;-1:-1:-1;10441:140:2;;;;;:::i;:::-;-1:-1:-1;;;;;10547:18:2;;;10521:7;10547:18;;;:11;:18;;;;;;;;:27;;;;;;;;;;;;;10441:140;6628:1864;;;;;;;;;;-1:-1:-1;6628:1864:2;;;;;:::i;:::-;;:::i;12742:232::-;12783:10;2520:42;12783:19;12779:43;;12811:11;;-1:-1:-1;;;12811:11:2;;;;;;;;;;;12779:43;12836:8;;;;;;;12832:38;;;12853:17;;-1:-1:-1;;;12853:17:2;;;;;;;;;;;12832:38;12880:22;:20;:22::i;:::-;12912:8;:15;;-1:-1:-1;;12912:15:2;;;;;12942:25;;;;;;12951:15;2773:25:7;;2761:2;2746:18;;2627:177;12942:25:2;;;;;;;;12742:232::o;11438:203::-;11507:28;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;11565:26:2;;:::i;:::-;-1:-1:-1;;11607:27:2;;;;;;;;;11615:6;11607:27;-1:-1:-1;;;;;11607:27:2;;;;;-1:-1:-1;;;11607:27:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11623:4;11607:27;;;;;;;;;;;;;;;;;;;;11629:4;11607:27;;;;;;-1:-1:-1;;;11607:27:2;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11607:27:2;;;;;;;;;;;-1:-1:-1;;;11607:27:2;;;;;;;;;;;;;-1:-1:-1;11607:27:2;11438:203::o;4350:192::-;4457:10;4417:12;4477:18;;;:11;:18;;;;;;;;-1:-1:-1;;;;;4477:28:2;;;;;;;;;;:37;;;4350:192;;;;;:::o;3922:422::-;4004:12;-1:-1:-1;;;;;4032:17:2;;;;:32;;-1:-1:-1;4053:11:2;;4032:32;4028:62;;;4073:17;;-1:-1:-1;;;4073:17:2;;;;;;;;;;;4028:62;-1:-1:-1;;;;;4104:19:2;;4113:10;4104:19;4100:178;;-1:-1:-1;;;;;4143:18:2;;;;;;:11;:18;;;;;;;;4162:10;4143:30;;;;;;;;:39;-1:-1:-1;4139:74:2;;;4191:22;;-1:-1:-1;;;4191:22:2;;;;;;;;;;;4139:74;-1:-1:-1;;;;;4227:18:2;;;;;;:11;:18;;;;;;;;4246:10;4227:30;;;;;;;:40;;4261:6;;4227:18;:40;;4261:6;;4227:40;:::i;:::-;;;;-1:-1:-1;;4100:178:2;4287:29;4297:5;4304:3;4309:6;4287:9;:29::i;:::-;-1:-1:-1;4333:4:2;3922:422;;;;;;:::o;11647:211::-;11718:28;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;11776:26:2;;:::i;:::-;-1:-1:-1;;11818:33:2;;;;;;;;;11826:8;11818:33;-1:-1:-1;;;;;11818:33:2;;;;;-1:-1:-1;;;11818:33:2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;11836:6;11818:33;;;;;;;;;;;;;;;;;;;;11844:6;11818:33;;;;;;-1:-1:-1;;;11818:33:2;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11818:33:2;;;;;;;;;;;-1:-1:-1;;;11818:33:2;;;;;;;;;;;;;-1:-1:-1;11818:33:2;11647:211::o;9230:183::-;9278:12;9302:25;9308:10;9320:6;9302:5;:25::i;:::-;-1:-1:-1;9366:40:2;;2773:25:7;;;9347:4:2;;9395:1;;9375:10;;-1:-1:-1;;;;;;;;;;;9366:40:2;2761:2:7;2746:18;9366:40:2;;;;;;;9230:183;;;:::o;12249:165::-;12303:10;2520:42;12303:19;12299:43;;12331:11;;-1:-1:-1;;;12331:11:2;;;;;;;;;;;12299:43;-1:-1:-1;;;;;12352:15:2;;;;;;:9;:15;;;;;;:22;;-1:-1:-1;;12352:22:2;12370:4;12352:22;;;12389:18;;;12352:15;12389:18;12249:165;:::o;4726:1896::-;2946:6;;4771:14;;2946:6;;2956:1;2946:11;2942:36;;2966:12;;-1:-1:-1;;;2966:12:2;;;;;;;;;;;2942:36;2988:6;:10;;-1:-1:-1;;2988:10:2;2997:1;2988:10;;;4819:4:::1;:15:::0;::::1;;4801;:33;4797:60;;;4843:14;;-1:-1:-1::0;;;4843:14:2::1;;;;;;;;;;;4797:60;4871:6;:15:::0;-1:-1:-1;;;;;4871:15:2::1;:20:::0;4867:1749:::1;;4978:36;5017:6;4978:45;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;4978:45:2::1;-1:-1:-1::0;;;;;4978:45:2::1;-1:-1:-1::0;;;;;4978:45:2::1;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;4978:45:2::1;-1:-1:-1::0;;;;;4978:45:2::1;-1:-1:-1::0;;;;;4978:45:2::1;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;4978:45:2::1;-1:-1:-1::0;;;;;4978:45:2::1;-1:-1:-1::0;;;;;4978:45:2::1;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;4978:45:2::1;-1:-1:-1::0;;;;;4978:45:2::1;-1:-1:-1::0;;;;;4978:45:2::1;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;4978:45:2::1;-1:-1:-1::0;;;;;4978:45:2::1;-1:-1:-1::0;;;;;4978:45:2::1;;;::::0;::::1;;;5037:32;5072:4;5037:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;5090:32;5125:4;5090:39;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;5143:44;5190:10;5143:57;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;5143:57:2::1;-1:-1:-1::0;;;;;5143:57:2::1;-1:-1:-1::0;;;;;5143:57:2::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;5214:15;5232:12;;5214:30;;5258:11;5279:15;5258:37;;5421:55;5442:4;5421:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;5448:7;5457:5;5464:11;5421:20;:55::i;:::-;5382:94;;;;;;;;;;;;;;;;5491:13;5507:77;5534:5;:21;;;5557:7;:17;;;-1:-1:-1::0;;;;;5507:77:2::1;5576:7;5507:26;:77::i;:::-;5491:93:::0;-1:-1:-1;5491:93:2;5609:16:::1;:9;5621:4;5609:16;:::i;:::-;:24;;;;:::i;:::-;5661:16:::0;;5599:35;;-1:-1:-1;;;;;;5661:16:2::1;5652:25:::0;::::1;5648:49;;;5686:11;;-1:-1:-1::0;;;5686:11:2::1;;;;;;;;;;;5648:49;5778:6;5751:7;:16;;:34;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;5751:34:2::1;::::0;;-1:-1:-1;5799:17:2::1;::::0;::::1;:38:::0;;5827:9:::1;::::0;5799:17;:38:::1;::::0;5827:9;;5799:38:::1;:::i;:::-;-1:-1:-1::0;;;;;5799:38:2::1;::::0;;-1:-1:-1;5851:12:2::1;::::0;::::1;:30:::0;;5874:6;;5851:12;:30:::1;::::0;5874:6;;5851:30:::1;:::i;:::-;-1:-1:-1::0;;;;;5851:30:2::1;::::0;;-1:-1:-1;5895:17:2::1;::::0;::::1;:35:::0;;5923:6;;5895:17;:35:::1;::::0;5923:6;;5895:35:::1;:::i;:::-;-1:-1:-1::0;;;;;5895:35:2::1;::::0;;-1:-1:-1;5945:12:2::1;5960:25;5966:10;5978:6:::0;5960:5:::1;:25::i;:::-;5945:40;;6004:7;5999:33;;6020:12;;-1:-1:-1::0;;;6020:12:2::1;;;;;;;;;;;5999:33;6051:31;::::0;;5483:25:7;;;5539:2;5524:18;;5517:34;;;6056:10:2::1;::::0;6051:31:::1;::::0;5456:18:7;6051:31:2::1;;;;;;;6211:70;6231:4;6237:7;6246:5;6253;6260:11;6273:7;6211:19;:70::i;:::-;6337:16:::0;;:6:::1;:16:::0;;::::1;::::0;;::::1;::::0;-1:-1:-1;;;;;6337:16:2;;::::1;-1:-1:-1::0;;;;;;6337:16:2;;;;-1:-1:-1;;;6337:16:2;;::::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;;;;;;6337:16:2;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;6367:12;;:4:::1;:12:::0;;-1:-1:-1;;6367:12:2::1;;::::0;;::::1;;::::0;;;;::::1;::::0;;;6393;;:4:::1;:12:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;-1:-1:-1;;;;6393:12:2;;::::1;::::0;;;;;;;;-1:-1:-1;;;6393:12:2;;::::1;::::0;;;::::1;;::::0;;;;;;::::1;::::0;;::::1;-1:-1:-1::0;;;;6393:12:2;;;;;-1:-1:-1;;;6393:12:2;;::::1;::::0;;;::::1;::::0;;;::::1;-1:-1:-1::0;;;;6393:12:2::1;-1:-1:-1::0;;;6393:12:2;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;6419:24;;-1:-1:-1;6419:24:2;;;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;-1:-1:-1;;;;;6419:24:2;;::::1;-1:-1:-1::0;;;;;;6419:24:2;;;;;;;-1:-1:-1;;;6419:24:2;;::::1;::::0;;;::::1;::::0;;;::::1;-1:-1:-1::0;;;;6419:24:2;-1:-1:-1;;;6419:24:2;;;::::1;;-1:-1:-1::0;;;;6419:24:2;;;;;-1:-1:-1;;;6419:24:2;::::1;;::::0;;;::::1;;::::0;;-1:-1:-1;4867:1749:2::1;::::0;-1:-1:-1;;;;;;;4867:1749:2::1;;6551:54;6583:10;6595:9;6551:31;:54::i;:::-;3019:6:::0;:10;;-1:-1:-1;;3019:10:2;3028:1;3019:10;;;4726:1896;:::o;11120:105::-;11166:7;11192:26;11212:5;11192:19;:26::i;:::-;11185:33;;11120:105;:::o;13236:991::-;13320:10;2520:42;13320:19;;;;:52;;-1:-1:-1;13343:10:2;2611:42;13343:29;;13320:52;13316:80;;;13381:15;;-1:-1:-1;;;13381:15:2;;;;;;;;;;;13316:80;13410:4;:15;13428;13410;;;;:33;13406:60;;;13452:14;;-1:-1:-1;;;13452:14:2;;;;;;;;;;;13406:60;13718:4;13675:22;13700:24;;;;;;;;;;;13738:18;;13734:251;;13818:4;13800:9;:24;;;;;;;;;;;:42;;;;;;;13860:12;:30;;;;;;;13923:51;2773:25:7;;;13800:9:2;;13818:4;-1:-1:-1;;;;;;;;;;;13923:51:2;2746:18:7;13923:51:2;;;;;;;13734:251;13994:13;14010:28;14026:12;14010:13;:28;:::i;:::-;13994:44;;14048:46;14061:10;14081:4;14088:5;14048:12;:46::i;:::-;-1:-1:-1;14104:15:2;:31;;;14145:14;:29;;;14184:9;:7;:9::i;:::-;14203:17;:15;:17::i;:::-;13306:921;;13236:991;;:::o;3695:221::-;3758:12;-1:-1:-1;;;;;3786:17:2;;;;:32;;-1:-1:-1;3807:11:2;;3786:32;3782:62;;;3827:17;;-1:-1:-1;;;3827:17:2;;;;;;;;;;;3782:62;3854:34;3864:10;3876:3;3881:6;3854:9;:34::i;:::-;-1:-1:-1;3905:4:2;3695:221;;;;:::o;11302:130::-;11412:12;;11352:7;;11380:28;:21;11404:4;11380:28;:::i;:::-;11379:45;;;;:::i;11012:102::-;11056:7;11082:25;11102:4;11082:19;:25::i;12515:159::-;12569:10;2520:42;12569:19;12565:43;;12597:11;;-1:-1:-1;;;12597:11:2;;;;;;;;;;;12565:43;-1:-1:-1;;;;;12618:12:2;;;;;;:5;:12;;;;;;;;;:19;;-1:-1:-1;;12618:19:2;12633:4;12618:19;;;12652:15;;2565:51:7;;;12652:15:2;;2538:18:7;12652:15:2;;;;;;;12515:159;:::o;8719:405::-;8769:14;8836:13;8852:58;8868:21;8891:4;8897:12;;8852:15;:58::i;:::-;8836:74;;8929:36;8945:5;8952:6;8960:4;8929:15;:36::i;:::-;8920:45;;8975:25;8981:10;8993:6;8975:5;:25::i;:::-;9010:51;9042:10;9054:6;9010:31;:51::i;:::-;9076:41;;;5894:25:7;;;5950:2;5935:18;;5928:34;;;5978:18;;;5971:34;;;9083:10:2;;9076:41;;5882:2:7;5867:18;9076:41:2;;;;;;;8785:339;8719:405;;;:::o;6628:1864::-;2946:6;;6684:14;;2946:6;;2956:1;2946:11;2942:36;;2966:12;;-1:-1:-1;;;2966:12:2;;;;;;;;;;;2942:36;2988:6;:10;;-1:-1:-1;;2988:10:2;2997:1;2988:10;;;6732:6:::1;:17:::0;::::1;;6714:15;:35;6710:62;;;6758:14;;-1:-1:-1::0;;;6758:14:2::1;;;;;;;;;;;6710:62;6786:8;:17:::0;-1:-1:-1;;;;;6786:17:2::1;:22:::0;6782:1704:::1;;6824:81;::::0;-1:-1:-1;;;6824:81:2;;6857:10:::1;6824:81;::::0;::::1;6256:34:7::0;2611:42:2::1;6306:18:7::0;;;6299:43;6358:18;;;6351:34;;;6838:4:2::1;-1:-1:-1::0;;;;;6824:32:2::1;::::0;::::1;::::0;6191:18:7;;6824:81:2::1;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;6990:36;7029:8;6990:47;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;6990:47:2::1;-1:-1:-1::0;;;;;6990:47:2::1;-1:-1:-1::0;;;;;6990:47:2::1;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;6990:47:2::1;-1:-1:-1::0;;;;;6990:47:2::1;-1:-1:-1::0;;;;;6990:47:2::1;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;6990:47:2::1;-1:-1:-1::0;;;;;6990:47:2::1;-1:-1:-1::0;;;;;6990:47:2::1;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;6990:47:2::1;-1:-1:-1::0;;;;;6990:47:2::1;-1:-1:-1::0;;;;;6990:47:2::1;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;6990:47:2::1;-1:-1:-1::0;;;;;6990:47:2::1;-1:-1:-1::0;;;;;6990:47:2::1;;;::::0;::::1;;;7051:32;7086:6;7051:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;7106:32;7141:6;7106:41;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;7161:44;7208:12;7161:59;;;;;;;;;;;;;;;;;;;;-1:-1:-1::0;;;;;7161:59:2::1;-1:-1:-1::0;;;;;7161:59:2::1;-1:-1:-1::0;;;;;7161:59:2::1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;;;7234:15;7252:12;;7234:30;;7278:11;7299:15;7278:37;;7441:57;7462:6;7441:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;7470:7;7479:5;7486:11;7441:20;:57::i;:::-;7402:96;;;;;;;;;;;;;;;;7513:13;7529:77;7556:5;:21;;;7579:7;:17;;;-1:-1:-1::0;;;;;7529:77:2::1;7598:7;7529:26;:77::i;:::-;7513:93:::0;-1:-1:-1;7513:93:2;7631:16:::1;:9:::0;7643:4:::1;7631:16;:::i;:::-;:24;;;;:::i;:::-;7683:18:::0;;7621:35;;-1:-1:-1;;;;;;7683:18:2::1;7674:27:::0;::::1;7670:51;;;7710:11;;-1:-1:-1::0;;;7710:11:2::1;;;;;;;;;;;7670:51;7802:6;7775:7;:16;;:34;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;7775:34:2::1;::::0;;-1:-1:-1;7823:17:2::1;::::0;::::1;:38:::0;;7851:9;;7823:17;:38:::1;::::0;7851:9;;7823:38:::1;:::i;:::-;-1:-1:-1::0;;;;;7823:38:2::1;::::0;;-1:-1:-1;7875:12:2::1;::::0;::::1;:30:::0;;7898:6;;7875:12;:30:::1;::::0;7898:6;;7875:30:::1;:::i;:::-;-1:-1:-1::0;;;;;7875:30:2::1;::::0;;-1:-1:-1;7919:17:2::1;::::0;::::1;:35:::0;;7947:6;;7919:17;:35:::1;::::0;7947:6;;7919:35:::1;:::i;:::-;-1:-1:-1::0;;;;;7919:35:2::1;::::0;;-1:-1:-1;7969:12:2::1;7984:25;7990:10;8002:6:::0;7984:5:::1;:25::i;:::-;7969:40;;8028:7;8023:33;;8044:12;;-1:-1:-1::0;;;8044:12:2::1;;;;;;;;;;;8023:33;8075:31;::::0;;5483:25:7;;;5539:2;5524:18;;5517:34;;;8080:10:2::1;::::0;8075:31:::1;::::0;5456:18:7;8075:31:2::1;;;;;;;8235:70;8255:4;8261:7;8270:5;8277;8284:11;8297:7;8235:19;:70::i;:::-;8361:18:::0;;:8:::1;:18:::0;;::::1;::::0;;::::1;::::0;-1:-1:-1;;;;;8361:18:2;;::::1;-1:-1:-1::0;;;;;;8361:18:2;;;;-1:-1:-1;;;8361:18:2;;::::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;;;;;;8361:18:2;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;8393:14;;:6:::1;:14:::0;;-1:-1:-1;;8393:14:2::1;;::::0;;::::1;;::::0;;;;::::1;::::0;;;8421;;:6:::1;:14:::0;;;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;-1:-1:-1;;;;8421:14:2;;::::1;::::0;;;;;;;;-1:-1:-1;;;8421:14:2;;::::1;::::0;;;::::1;;::::0;;;;;;::::1;::::0;;::::1;-1:-1:-1::0;;;;8421:14:2;;;;;-1:-1:-1;;;8421:14:2;;::::1;::::0;;;::::1;::::0;;;::::1;-1:-1:-1::0;;;;8421:14:2::1;-1:-1:-1::0;;;8421:14:2;;::::1;::::0;;;::::1;::::0;;;::::1;::::0;;8449:26;;8361:18:::1;8449:26:::0;;;;::::1;::::0;;;::::1;::::0;;;;::::1;::::0;-1:-1:-1;;;;;8449:26:2;;::::1;-1:-1:-1::0;;;;;;8449:26:2;;;;;;;-1:-1:-1;;;8449:26:2;;::::1;::::0;;;::::1;::::0;;;::::1;-1:-1:-1::0;;;;8449:26:2;-1:-1:-1;;;8449:26:2;;;::::1;;-1:-1:-1::0;;;;8449:26:2;;;;;-1:-1:-1;;;8449:26:2;::::1;;::::0;;;::::1;;::::0;;-1:-1:-1;;;;;;;;6782:1704:2::1;3019:6:::0;:10;;-1:-1:-1;;3019:10:2;3028:1;3019:10;;;6628:1864;;-1:-1:-1;6628:1864:2:o;15136:708::-;15186:19;15208:9;:24;15226:4;-1:-1:-1;;;;;15208:24:2;-1:-1:-1;;;;;15208:24:2;;;;;;;;;;;;;15186:46;;15282:4;15276:11;-1:-1:-1;;;15307:3:2;15300:79;-1:-1:-1;;;;;15416:9:2;15412:58;15408:1;15403:3;15399:11;15392:79;15505:11;15500:2;15495:3;15491:12;15484:33;15551:1;15546:2;15541:3;15537:12;15530:23;15588:1;15582:3;15577;15573:13;15566:24;15625:15;15619:3;15614;15610:13;15603:38;15676:11;15670:3;15665;15661:13;15654:34;15779:1;15776;15771:3;15766;15754:9;15746:18;15727:17;15720:5;15715:66;15701:80;;15804:6;15794:34;;15824:1;15821;15814:12;15794:34;;15251:587;15136:708::o;20113:856::-;-1:-1:-1;;;;;20205:15:2;;:9;:15;;;;;;;;;;;20196:24;;20192:57;;;20229:20;;-1:-1:-1;;;20229:20:2;;;;;;;;;;;20192:57;-1:-1:-1;;;;;20282:9:2;;20259;20282;;;:5;:9;;;;;;;;;:24;;-1:-1:-1;;;;;;20295:11:2;;;;;;:5;:11;;;;;;;;20282:24;20278:187;;;-1:-1:-1;;;;;20326:13:2;;;;;;:9;:13;;;;;;;;;:32;;-1:-1:-1;;;;;;20343:15:2;;;;;;:9;:15;;;;;;;;20326:32;20322:133;;;-1:-1:-1;20385:5:2;20322:133;;;-1:-1:-1;20436:4:2;20322:133;20478:4;20474:448;;;20498:11;20529:4;20513:12;2173:2;20513:6;:12;:::i;:::-;20512:21;;;;:::i;:::-;-1:-1:-1;;;;;20576:15:2;;:9;:15;;;;;;;;;;:25;;;;;;;2611:42;20619:26;;;:33;;;;;;20498:35;-1:-1:-1;20680:13:2;20498:35;20595:6;20680:13;:::i;:::-;-1:-1:-1;;;;;20735:13:2;;:9;:13;;;;;;;;;;:23;;;;;;20680:13;-1:-1:-1;20474:448:2;;-1:-1:-1;20474:448:2;;-1:-1:-1;;;;;20831:15:2;;;:9;:15;;;;;;;;;;;:25;;;;;;;20874:13;;;;;;:23;;;;;;20474:448;20951:2;-1:-1:-1;;;;;20936:26:2;20945:4;-1:-1:-1;;;;;20936:26:2;-1:-1:-1;;;;;;;;;;;20955:6:2;20936:26;;;;2773:25:7;;2761:2;2746:18;;2627:177;20936:26:2;;;;;;;;20182:787;20113:856;;;:::o;21571:276::-;-1:-1:-1;;;;;21637:15:2;;:9;:15;;;;;;;;;;;:23;-1:-1:-1;21633:56:2;;;21669:20;;-1:-1:-1;;;21669:20:2;;;;;;;;;;;21633:56;-1:-1:-1;;;;;21723:15:2;;:9;:15;;;;;;;;;;;:24;;;;;;;21761:12;:21;;;;;;;21807:33;2773:25:7;;;21723:9:2;;:15;-1:-1:-1;;;;;;;;;;;21807:33:2;2746:18:7;21807:33:2;;;;;;;21571:276;;:::o;1054:845:3:-;1206:13;;:::i;:::-;1221:11;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1301:15:3;1347:23;1357:4;1363:6;1347:9;:23::i;:::-;1327:43;;:6;:16;;:43;;;;;;;:::i;:::-;-1:-1:-1;;;;;1327:43:3;;;-1:-1:-1;1380:21:3;;;:14;;;:21;1416:18;;;;1412:430;;;1451:16;1469:9;1480:16;1500:25;1513:11;1500:12;:25::i;:::-;1450:75;;;;;;1564:8;-1:-1:-1;;;;;1539:33:3;:5;:21;;:33;;;;;;;:::i;:::-;;;-1:-1:-1;1586:246:3;;;;1643:8;1621:11;:18;;:30;;;;;;;:::i;:::-;-1:-1:-1;;;;;1621:30:3;;;-1:-1:-1;1669:26:3;;;:32;;1699:2;;1669:26;:32;;1699:2;;1669:32;:::i;:::-;;;;;;;;1719:33;;:26;;;:33;-1:-1:-1;1586:246:3;;;1812:5;1791:18;;;:26;1586:246;1436:406;;;1412:430;-1:-1:-1;1859:6:3;;1873:5;;-1:-1:-1;1880:11:3;;1054:845;-1:-1:-1;;;1054:845:3:o;2341:238::-;2477:7;2567:4;2528:35;2538:10;2550:12;2528:9;:35::i;:::-;2509:54;;:16;:54;:::i;:::-;2508:63;;;;:::i;:::-;2500:72;2341:238;-1:-1:-1;;;;2341:238:3:o;22085:348:2:-;22198:4;22144:12;22180:24;;;;;;;;;;;22172:32;;22168:72;;;22213:27;;-1:-1:-1;;;22213:27:2;;;;;;;;;;;22168:72;-1:-1:-1;;;;;;22274:13:2;;:9;:13;;;;;;;;;;;:22;;;;;;22328:4;22310:24;;;;;;;:33;;;;;;;22392:34;2773:25:7;;;-1:-1:-1;;22274:13:2;22328:4;-1:-1:-1;;;;;;;;;;;22392:34:2;2746:18:7;22392:34:2;;;;;;;22085:348;;;;:::o;3139:1200:3:-;3353:13;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;3381:11:3;;:::i;:::-;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3423:22:3;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3423:22:3;3483:17;;;;3467:13;;:33;;3483:17;3467:33;:::i;:::-;3459:41;;:4;:41;;;3455:829;;3534:15;;:22;;3552:4;;3534:22;:::i;:::-;3516:40;;;;3596:20;;;;;3618:16;;;;3584:65;;3596:20;-1:-1:-1;;;;;3584:65:3;3636:12;3584:11;:65::i;:::-;3570:11;;;:79;3680:15;;-1:-1:-1;;;;;3663:32:3;:14;;;:32;;;3776:15;;3753:20;;;;3776:15;;3736:37;;;;;;:::i;:::-;:55;;;;:::i;:::-;-1:-1:-1;;;;;3709:84:3;:16;;;;:84;;;;3857:15;;3843:11;;;;3826:14;;;;3857:15;;3826:28;;;;;;;;:::i;:::-;:46;;;;:::i;:::-;3807:16;;;:65;;;3899:11;;;;:26;;3913:12;;3899:26;:::i;:::-;3898:47;;;;:::i;:::-;3886:9;;;:59;;;3976:20;;;;-1:-1:-1;3960:280:3;;;4016:14;4064:5;:9;;;4041:4;:20;;;:32;;;;:::i;:::-;4016:58;;4105:49;;;;;;;;4116:6;-1:-1:-1;;;;;4105:49:3;;;;;4124:4;4105:49;;;;;;4130:4;:17;;;4105:49;;;;;;4149:4;4105:49;;;;;4092:62;;3998:171;3960:280;;;4216:9;;;;4193:20;;;:32;3960:280;4253:20;;;;;3455:829;-1:-1:-1;4301:6:3;;4309:4;;-1:-1:-1;4315:4:3;;-1:-1:-1;4321:10:3;;3139:1200;-1:-1:-1;;;;3139:1200:3:o;799:339:1:-;871:12;1070:1;1067;1064;1061;1053:6;1049:2;1042:5;1037:35;1026:46;;1100:7;1092:39;;;;-1:-1:-1;;;1092:39:1;;7450:2:7;1092:39:1;;;7432:21:7;7489:2;7469:18;;;7462:30;-1:-1:-1;;;7508:18:7;;;7501:49;7567:18;;1092:39:1;;;;;;;;861:277;799:339;;:::o;25680:667:2:-;25741:7;25764:3;25760:581;;;25869:20;;25845:57;;;;;;;;25891:10;25845:57;-1:-1:-1;;;;;25845:57:2;;;;-1:-1:-1;;;25845:57:2;;;;;;;;;;-1:-1:-1;;;25845:57:2;;;;;;;;;;-1:-1:-1;;;25845:57:2;;;;;;;;;;;25808:216;;25845:57;;:23;:57::i;:::-;25949:6;:16;25967:12;;25924:56;;-1:-1:-1;;;25949:16:2;;-1:-1:-1;;;;;25949:16:2;;25924:24;:56::i;:::-;26002:4;25808:15;:216::i;25760:581::-;26155:22;;26131:61;;;;;;;;26179:12;26131:61;-1:-1:-1;;;;;26131:61:2;;;;-1:-1:-1;;;26131:61:2;;;;;;;;;;-1:-1:-1;;;26131:61:2;;;;;;;;;;-1:-1:-1;;;26131:61:2;;;;;;;;;;;26094:222;;26131:61;;:23;:61::i;:::-;26239:8;:18;26259:12;;26214:58;;-1:-1:-1;;;26239:18:2;;-1:-1:-1;;;;;26239:18:2;;26214:24;:58::i;25760:581::-;25680:667;;;:::o;16169:1394::-;16294:15;;16324:19;;16320:1208;;16359:20;16382:11;:9;:11::i;:::-;16359:34;-1:-1:-1;16426:10:2;16408:15;2807:6;16476:18;16426:10;16489:5;16476:18;:::i;:::-;-1:-1:-1;;;;;16476:29:2;;;;;:::i;:::-;16450:56;;16520:23;16576:10;-1:-1:-1;;;;;16546:40:2;16561:12;;16546;:27;;;;:::i;:::-;:40;;;;:::i;:::-;16520:66;;16600:11;16614:31;16622:8;-1:-1:-1;;;;;16614:31:2;16632:12;16614:7;:31::i;:::-;16600:45;-1:-1:-1;16659:17:2;16686:26;2807:6;16686:15;:26;:::i;:::-;16659:54;;16732:6;16728:790;;;16767:60;;;;;;;;;-1:-1:-1;;;;;16767:60:2;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;16767:60:2;;;;;;;;;;;;;;;16758:6;:69;;-1:-1:-1;;;;;;16758:69:2;;;;;-1:-1:-1;;;16758:69:2;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;16758:69:2;;;;;;16852:48;;;;;;;;;;;;;;;;;;;;16845:4;:55;;-1:-1:-1;;16845:55:2;;;;;;;;;16945:100;;;;;;;16972:15;16945:100;;;;;;;;;;;;2807:6;16945:100;;;;17033:5;16945:100;;;;17040:4;16945:100;;;;;;;;16918:4;:127;;;;;;;-1:-1:-1;;;16918:127:2;;;;;;;-1:-1:-1;;;;;;;;16918:127:2;-1:-1:-1;;;16918:127:2;;;17068:51;;8065:58:7;;;8139:18;;;8132:34;;;;8182:18;;;8175:55;;;;17068:51:2;;8038:18:7;17068:51:2;;;;;;;16728:790;;;17158:30;17172:4;17179:8;-1:-1:-1;;;;;17158:30:2;:5;:30::i;:::-;17439:26;2807:6;17439:15;:26;:::i;:::-;17414:4;:52;;-1:-1:-1;;17414:52:2;;;;;;;;;;;;17484:6;:19;;-1:-1:-1;;;;;;17484:19:2;;;16728:790;16345:1183;;;;;;16320:1208;-1:-1:-1;17555:1:2;17537:15;:19;16169:1394::o;17634:1345::-;17706:14;;-1:-1:-1;;;;;17735:14:2;;;17731:1214;;17765:20;17788:13;:11;:13::i;:::-;17765:36;-1:-1:-1;17833:10:2;17815:15;2807:6;17883:18;17833:10;17896:5;17883:18;:::i;:::-;-1:-1:-1;;;;;17883:29:2;;;;;:::i;:::-;17857:56;;17927:23;17983:10;-1:-1:-1;;;;;17953:40:2;17968:12;;17953;:27;;;;:::i;:::-;:40;;;;:::i;:::-;17927:66;;18007:11;18021:31;18029:8;-1:-1:-1;;;;;18021:31:2;18039:12;18021:7;:31::i;:::-;18007:45;-1:-1:-1;18066:17:2;18093:26;2807:6;18093:15;:26;:::i;:::-;18066:54;;18139:6;18135:800;;;18176:60;;;;;;;;;-1:-1:-1;;;;;18176:60:2;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;18176:60:2;;;;;;;;;;;;;;;18165:8;:71;;-1:-1:-1;;;;;;18165:71:2;;;;;-1:-1:-1;;;18165:71:2;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;18165:71:2;;;;;;18263:48;;;;;;;;;;;;;;;;;;;;18254:6;:57;;-1:-1:-1;;18254:57:2;;;;;;;;;18358:100;;;;;;;18385:15;18358:100;;;;;;;;;;;;2807:6;18358:100;;;;18446:5;18358:100;;;;18453:4;18358:100;;;;;;;;18329:6;:129;;;;;;;-1:-1:-1;;;18329:129:2;;;;;;;-1:-1:-1;;;;;;;;18329:129:2;-1:-1:-1;;;18329:129:2;;;18481:51;;8065:58:7;;;8139:18;;;8132:34;;;;8182:18;;;8175:55;;;;18481:51:2;;8038:18:7;18481:51:2;;;;;;;18135:800;;;18571:30;18585:4;18592:8;-1:-1:-1;;;;;18571:30:2;:5;:30::i;:::-;18854:26;2807:6;18854:15;:26;:::i;:::-;18827:6;:54;;-1:-1:-1;;18827:54:2;;;;;;;;;;;;18899:8;:21;;-1:-1:-1;;;;;;18899:21:2;;;18135:800;17751:1194;;;;;;17731:1214;-1:-1:-1;18971:1:2;18954:14;:18;17634:1345::o;741:4097:6:-;823:14;;;-1:-1:-1;;1386:1:6;1383;1376:20;1429:1;1426;1422:9;1413:18;;1484:5;1480:2;1477:13;1469:5;1465:2;1461:14;1457:34;1448:43;;;1585:5;1594:1;1585:10;1581:203;;1637:1;1623:11;:15;1615:24;;;;;;-1:-1:-1;1698:23:6;;;;-1:-1:-1;1756:13:6;;1581:203;1923:5;1909:11;:19;1901:28;;;;;;2230:17;2314:11;2311:1;2308;2301:25;2706:12;2722:15;;;2721:31;;2858:22;;;;;3733:1;3714;:15;;3713:21;;3976:17;;;3972:21;;3965:28;4038:17;;;4034:21;;4027:28;4101:17;;;4097:21;;4090:28;4164:17;;;4160:21;;4153:28;4227:17;;;4223:21;;4216:28;4291:17;;;4287:21;;;4280:28;3270:12;;;;3266:23;;;3291:1;3262:31;2459:20;;;2448:32;;;3329:12;;;;2506:21;;;;3002:16;;;;3320:21;;;;4783:11;;;;;-1:-1:-1;;741:4097:6;;;;;:::o;2744:234:3:-;2826:6;2844:20;2885:4;:14;;;2867:32;;:15;:32;;;;:::i;:::-;2844:55;;2959:4;:11;;;2923:47;;2943:12;2924:6;:16;;;-1:-1:-1;;;;;2924:31:3;;;;;:::i;1905:430::-;1974:7;1983:6;1991:4;2012;:11;;;2007:38;;-1:-1:-1;2033:1:3;;-1:-1:-1;2033:1:3;;-1:-1:-1;2033:1:3;2025:20;;2007:38;2056:19;2104:4;:19;;;2085:15;2078:45;;;;:::i;:::-;2056:67;;2133:11;2162:4;:19;;;2147:34;;:12;:34;;;2133:48;;2191:14;2208:6;:73;;2270:11;;2208:73;;;2248:4;:19;;;2217:50;;2232:12;2218:26;;:4;:11;;;:26;;;;:::i;:::-;2217:50;;;;:::i;:::-;2191:90;-1:-1:-1;2307:12:3;;-1:-1:-1;2321:6:3;-1:-1:-1;;1905:430:3;;;;;;:::o;2585:153::-;2669:7;2718:12;2697:17;:10;2710:4;2697:17;:::i;:::-;2696:34;;;;:::i;26353:266:2:-;26496:7;26520:13;26539:33;26567:4;26539:27;:33::i;:::-;-1:-1:-1;;;;;;;26519:53:2;;-1:-1:-1;26589:23:2;26519:53;26589:15;:23;:::i;22631:788::-;22674:13;22699;22715:4;22699:20;;22729:16;22755;22821:4;22815:11;-1:-1:-1;;;22846:3:2;22839:79;22982:1;22979;22976;22971:3;22964:5;22957;22946:38;22931:53;;23007:7;22997:35;;23028:1;23025;23018:12;22997:35;;23069:2;23066:1;23060:4;23045:27;23112:2;23106:4;23100;23085:30;-1:-1:-1;;23146:4:2;23140:11;23182:4;23176:11;23211:10;23207:206;;;23245:59;23269:8;-1:-1:-1;;;;;23261:17:2;23280:4;23294:8;-1:-1:-1;;;;;23286:17:2;23245:15;:59::i;:::-;23237:67;;23207:206;;;23343:59;23367:8;-1:-1:-1;;;;;23359:17:2;23378:4;23392:8;-1:-1:-1;;;;;23384:17:2;23343:15;:59::i;:::-;23335:67;;23207:206;22689:730;;;22631:788;:::o;19657:379::-;19771:12;;19729:13;;;19850:17;19859:8;19771:12;19850:17;:::i;:::-;19817:28;:21;19841:4;19817:28;:::i;:::-;19816:52;;;;:::i;:::-;19793:75;-1:-1:-1;19878:20:2;19959:6;19937:16;19948:5;19937:8;:16;:::i;:::-;19903:28;:21;19927:4;19903:28;:::i;:::-;19902:53;;;;:::i;:::-;19901:64;;;;:::i;:::-;19878:87;;20002:12;19986;:28;;:43;;20025:4;19986:43;;;20017:5;19986:43;19975:54;19657:379;-1:-1:-1;;;;;;19657:379:2:o;23488:1151::-;23533:16;23561:13;23577:4;23561:20;;23591:16;23617;23643:21;23714:4;23708:11;-1:-1:-1;;;23739:3:2;23732:79;23875:1;23872;23869;23864:3;23857:5;23850;23839:38;23900:7;23890:35;;23921:1;23918;23911:12;23890:35;;23962:2;23959:1;23953:4;23938:27;24005:2;23999:4;23993;23978:30;24039:4;24033:11;24021:23;;24075:4;24069:11;24057:23;;-1:-1:-1;;;24109:4:2;24104:3;24100:14;24093:90;24257:2;24254:1;24251;24244:4;24239:3;24235:14;24228:5;24221;24210:50;24196:64;;24296:4;24290:11;24273:28;;24443:10;24439:194;;;24480:50;24496:12;:8;24507:1;24496:12;:::i;:::-;-1:-1:-1;;;;;24480:50:2;24510:4;24516:13;24480:15;:50::i;:::-;24469:61;;24439:194;;;24572:50;24588:12;:8;24599:1;24588:12;:::i;24572:50::-;24561:61;;24439:194;23551:1088;;;;23488:1151;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;1237:548:7:-;1349:4;1378:2;1407;1396:9;1389:21;1439:6;1433:13;1482:6;1477:2;1466:9;1462:18;1455:34;1507:1;1517:140;1531:6;1528:1;1525:13;1517:140;;;1626:14;;;1622:23;;1616:30;1592:17;;;1611:2;1588:26;1581:66;1546:10;;1517:140;;;1521:3;1706:1;1701:2;1692:6;1681:9;1677:22;1673:31;1666:42;1776:2;1769;1765:7;1760:2;1752:6;1748:15;1744:29;1733:9;1729:45;1725:54;1717:62;;;;1237:548;;;;:::o;1790:173::-;1858:20;;-1:-1:-1;;;;;1907:31:7;;1897:42;;1887:70;;1953:1;1950;1943:12;1968:254;2036:6;2044;2097:2;2085:9;2076:7;2072:23;2068:32;2065:52;;;2113:1;2110;2103:12;2065:52;2136:29;2155:9;2136:29;:::i;:::-;2126:39;2212:2;2197:18;;;;2184:32;;-1:-1:-1;;;1968:254:7:o;2809:328::-;2886:6;2894;2902;2955:2;2943:9;2934:7;2930:23;2926:32;2923:52;;;2971:1;2968;2961:12;2923:52;2994:29;3013:9;2994:29;:::i;:::-;2984:39;;3042:38;3076:2;3065:9;3061:18;3042:38;:::i;:::-;3032:48;;3127:2;3116:9;3112:18;3099:32;3089:42;;2809:328;;;;;:::o;3331:180::-;3390:6;3443:2;3431:9;3422:7;3418:23;3414:32;3411:52;;;3459:1;3456;3449:12;3411:52;-1:-1:-1;3482:23:7;;3331:180;-1:-1:-1;3331:180:7:o;3516:186::-;3575:6;3628:2;3616:9;3607:7;3603:23;3599:32;3596:52;;;3644:1;3641;3634:12;3596:52;3667:29;3686:9;3667:29;:::i;3707:248::-;3775:6;3783;3836:2;3824:9;3815:7;3811:23;3807:32;3804:52;;;3852:1;3849;3842:12;3804:52;-1:-1:-1;;3875:23:7;;;3945:2;3930:18;;;3917:32;;-1:-1:-1;3707:248:7:o;3960:260::-;4028:6;4036;4089:2;4077:9;4068:7;4064:23;4060:32;4057:52;;;4105:1;4102;4095:12;4057:52;4128:29;4147:9;4128:29;:::i;:::-;4118:39;;4176:38;4210:2;4199:9;4195:18;4176:38;:::i;:::-;4166:48;;3960:260;;;;;:::o;4225:127::-;4286:10;4281:3;4277:20;4274:1;4267:31;4317:4;4314:1;4307:15;4341:4;4338:1;4331:15;4357:128;4424:9;;;4445:11;;;4442:37;;;4459:18;;:::i;4490:168::-;4563:9;;;4594;;4611:15;;;4605:22;;4591:37;4581:71;;4632:18;;:::i;4663:127::-;4724:10;4719:3;4715:20;4712:1;4705:31;4755:4;4752:1;4745:15;4779:4;4776:1;4769:15;4795:120;4835:1;4861;4851:35;;4866:18;;:::i;:::-;-1:-1:-1;4900:9:7;;4795:120::o;4920:191::-;-1:-1:-1;;;;;5047:10:7;;;5035;;;5031:27;;5070:12;;;5067:38;;;5085:18;;:::i;:::-;5067:38;4920:191;;;;:::o;5116:188::-;-1:-1:-1;;;;;5229:10:7;;;5241;;;5225:27;;5264:11;;;5261:37;;;5278:18;;:::i;5562:125::-;5627:9;;;5648:10;;;5645:36;;;5661:18;;:::i;6396:277::-;6463:6;6516:2;6504:9;6495:7;6491:23;6487:32;6484:52;;;6532:1;6529;6522:12;6484:52;6564:9;6558:16;6617:5;6610:13;6603:21;6596:5;6593:32;6583:60;;6639:1;6636;6629:12;6678:200;-1:-1:-1;;;;;6814:10:7;;;6802;;;6798:27;;6837:12;;;6834:38;;;6852:18;;:::i;6883:179::-;6951:14;6998:10;;;6986;;;6982:27;;7021:12;;;7018:38;;;7036:18;;:::i;7067:176::-;7134:14;7168:10;;;7180;;;7164:27;;7203:11;;;7200:37;;;7217:18;;:::i;7596:265::-;-1:-1:-1;;;;;7725:10:7;;;7737;;;7721:27;7768:20;;;;7667:26;7807:24;;;7797:58;;7835:18;;:::i;:::-;7797:58;;7596:265;;;;:::o;8241:274::-;-1:-1:-1;;;;;8379:10:7;;;8391;;;8375:27;8422:20;;;;8313:34;8461:24;;;8451:58;;8489:18;;:::i;8520:216::-;8560:1;-1:-1:-1;;;;;8647:2:7;8644:1;8640:10;8669:3;8659:37;;8676:18;;:::i;:::-;8714:10;;8710:20;;;;;8520:216;-1:-1:-1;;8520:216:7:o;8741:270::-;-1:-1:-1;;;;;8875:10:7;;;8887;;;8871:27;8918:20;;;;8813:30;8957:24;;;8947:58;;8985:18;;:::i

Swarm Source

ipfs://caf4e3b4220f06c011dec8269de8b0005be17a0e02575fba2b57079b228073c0

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.