Overview
S Balance
0 S
S Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
2041079 | 34 days ago | Contract Creation | 0 S |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
OnchainCLOB
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1 // Central Limit Order Book (CLOB) exchange // (c) Long Gamma Labs, 2023. pragma solidity ^0.8.26; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; import {PausableUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol"; import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import {FixedPointMathLib} from "@solmate/src/utils/FixedPointMathLib.sol"; import {Errors} from "./Errors.sol"; import {FP24} from "./FP24.sol"; import {IWatchDog} from "./IWatchDog.sol"; import {IOnchainCLOB} from "./IOnchainCLOB.sol"; import {ITrie} from "./ITrie.sol"; import {ITrieFactory} from "./ITrieFactory.sol"; import {ITradeConsumer} from "./ITradeConsumer.sol"; import {IWETH} from "./IWETH.sol"; /// @title Trader structure /// @notice Used to represent a trader's state within the LOB contract /// @dev Stores trader's unique ID, token balances, and claimable status struct Trader { uint64 trader_id; ///< Unique identifier for the trader uint128 token_x; ///< Balance of token X for the trader uint128 token_y; ///< Balance of token Y for the trader bool claimable; ///< Flag indicating if the trader's orders are claimable "automatically" } /// @title Execution Result /// @notice Structure to store information about the result of aggressive or immediate part of order execution /// @dev Used to return data about the executed order from execution functions struct ExecutionResult { uint64 order_id; /// order_id Unique identifier of the order uint128 executed_shares; /// executed_shares Number of shares/tokens executed in the aggressive part uint128 executed_value; /// executed_value Total value of the aggressively executed part of the order uint128 aggressive_fee; /// aggressive_fee Fee for the aggressive execution } /// @title Market maker configuration struct MarketMakerConfig { address marketmaker; /// Market maker address bool should_invoke_on_trade; /// Invoke the onTrade method for the LP contract after each trade } /// @title Limit Order Book (LOB) Contract for Protocol /// @notice Implements an on-chain limit order book for trading pairs /// @dev Manages order placement, execution, and claiming processes contract OnchainCLOB is IOnchainCLOB, UUPSUpgradeable, Ownable2StepUpgradeable, ReentrancyGuardUpgradeable, PausableUpgradeable { using FixedPointMathLib for uint256; using SafeCast for uint256; using SafeERC20 for IERC20; event OrderPlaced( address indexed owner, uint64 order_id, bool indexed isAsk, uint128 quantity, uint72 price, uint128 passive_shares, uint128 passive_fee, uint128 aggressive_shares, uint128 aggressive_value, uint128 aggressive_fee, bool market_only, bool post_only ); event OrderClaimed( uint64 order_id, uint128 order_shares_remaining, uint128 token_x_sent, uint128 token_y_sent, uint128 passive_payout, bool only_claim ); event ClaimableStatusChanged( address indexed owner, bool status ); event MarketMakerChanged( address new_marketmaker, address old_marketmaker ); event PauserChanged( address new_pauser, address old_pauser ); event Deposited( address indexed owner, uint128 token_x, uint128 token_y ); event Withdrawn( address indexed owner, uint128 token_x, uint128 token_y ); uint8 constant nonce_length = 39; uint8 constant price_length = 24; uint256 constant wad = 1e18; uint256 scaling_factor_token_x; uint256 scaling_factor_token_y; IERC20 token_x; IERC20 token_y; bool supports_native_eth; bool is_token_x_weth; ITrie askTrie; ITrie bidTrie; uint64 admin_commission_rate; uint64 total_aggressive_commission_rate; // for market orders uint64 total_passive_commission_rate; // for out-of-money limit orders uint64 passive_order_payout_rate; MarketMakerConfig public marketmaker_config; address public pauser; uint64 public nonce; IWatchDog immutable watch_dog; uint64 last_used_trader_id; mapping (address => Trader) traders; uint256 accumulated_fees; modifier ensure(uint256 expires) { if (block.timestamp > expires) { revert Errors.Expired(); } _; } constructor(address _watch_dog) { watch_dog = IWatchDog(_watch_dog); _disableInitializers(); } /// @notice Initialize lob contract state /// @dev Method is used instead of a constructor to initialize the contract state for compatibility with Upgradeable logic /// @param _trie_factory Trie factory /// @param _tokenXAddress Token X address /// @param _tokenYAddress Token Y address /// @param _supports_native_eth Indicates if the contract supports native ETH transactions /// @param _is_token_x_weth Indicates if token X is WETH (Wrapped Ether) /// @param scaling_token_x Scaling factor for token X /// @param scaling_token_y Scaling factor for token Y /// @param _administrator Administrator address /// @param _marketmaker Market maker address /// @param _pauser Pauser address /// @param _should_invoke_on_trade Flag indicating whether to invoke the onTrade method for the LP contract after each trade /// @param _admin_commission_rate The commission rate for the administrator /// @param _total_aggressive_commission_rate The total commission rate for aggressive orders /// @param _total_passive_commission_rate The total commission rate for passive orders /// @param _passive_order_payout_rate Payout for passive orders function initialize( address _trie_factory, address _tokenXAddress, address _tokenYAddress, bool _supports_native_eth, bool _is_token_x_weth, uint256 scaling_token_x, uint256 scaling_token_y, address _administrator, address _marketmaker, address _pauser, bool _should_invoke_on_trade, uint64 _admin_commission_rate, uint64 _total_aggressive_commission_rate, uint64 _total_passive_commission_rate, uint64 _passive_order_payout_rate ) public initializer { __UUPSUpgradeable_init(); __Ownable_init(_administrator); __Ownable2Step_init(); __ReentrancyGuard_init(); __Pausable_init(); require(_trie_factory != address(0), Errors.AddressIsZero()); require(_tokenXAddress != address(0), Errors.AddressIsZero()); require(_tokenYAddress != address(0), Errors.AddressIsZero()); nonce = (uint64(1) << nonce_length) - uint64(1); last_used_trader_id = 0; scaling_factor_token_x = scaling_token_x; scaling_factor_token_y = scaling_token_y; token_x = IERC20(_tokenXAddress); token_y = IERC20(_tokenYAddress); supports_native_eth = _supports_native_eth; is_token_x_weth = _is_token_x_weth; ITrieFactory trie_factory = ITrieFactory(_trie_factory); address ask_trie_address = trie_factory.createTrie(address(this)); askTrie = ITrie(ask_trie_address); address bid_trie_address = trie_factory.createTrie(address(this)); bidTrie = ITrie(bid_trie_address); pauser = _pauser; _changeMarketMaker(_marketmaker, _should_invoke_on_trade); uint256 max_rate = 2e17; // 20% require( _admin_commission_rate <= 1e18 && _total_aggressive_commission_rate <= max_rate && _total_passive_commission_rate <= max_rate && _passive_order_payout_rate <= max_rate && (_passive_order_payout_rate == 0 || _total_passive_commission_rate == 0), Errors.InvalidCommissionRate() ); admin_commission_rate = _admin_commission_rate; total_aggressive_commission_rate = _total_aggressive_commission_rate; total_passive_commission_rate = _total_passive_commission_rate; passive_order_payout_rate = _passive_order_payout_rate; accumulated_fees = 1; // This is a simple trick to avoid zeroing out issue } /// @notice Returns the contract configuration /// @dev This function provides access to the main contract parameters such as scaling factors, commissions, and token addresses /// @return _scaling_factor_token_x Scaling factor for token X /// @return _scaling_factor_token_y Scaling factor for token Y /// @return _token_x Address of token X /// @return _token_y Address of token Y /// @return _supports_native_eth Indicates if the contract supports native ETH transactions /// @return _is_token_x_weth Indicates if token X is WETH (Wrapped Ether) /// @return _ask_trie Address of askTrie /// @return _bid_trie Address of bidTrie /// @return _admin_commission_rate The commission rate for the administrator /// @return _total_aggressive_commission_rate The total commission rate for aggressive orders /// @return _total_passive_commission_rate The total commission rate for passive orders /// @return _passive_order_payout_rate Payout for passive orders /// @return _should_invoke_on_trade Flag indicating whether to invoke the onTrade method for the LP contract after each trade function getConfig() external view returns ( uint256 _scaling_factor_token_x, uint256 _scaling_factor_token_y, address _token_x, address _token_y, bool _supports_native_eth, bool _is_token_x_weth, address _ask_trie, address _bid_trie, uint64 _admin_commission_rate, uint64 _total_aggressive_commission_rate, uint64 _total_passive_commission_rate, uint64 _passive_order_payout_rate, bool _should_invoke_on_trade ) { return ( scaling_factor_token_x, scaling_factor_token_y, address(token_x), address(token_y), supports_native_eth, is_token_x_weth, address(askTrie), address(bidTrie), admin_commission_rate, total_aggressive_commission_rate, total_passive_commission_rate, passive_order_payout_rate, marketmaker_config.should_invoke_on_trade ); } /// @notice Fallback function to handle incoming ETH deposits. receive() external payable { require(supports_native_eth && ( (is_token_x_weth && msg.sender == address(token_x)) ||(!is_token_x_weth && msg.sender == address(token_y)) ), Errors.Forbidden() ); } /// @notice Retrieves the balance of a trader by address in tokens stored on the LOB contract /// @dev Returns the balances of tokens X and Y, and the claimable status for the specified address /// @param address_ The address of the trader for whom the balance is being retrieved /// @return token_x Balance of token X for the trader /// @return token_y Balance of token Y for the trader /// @return claimable Status indicating whether the user's orders can be automatically claimed from other addresses function getTraderBalance(address address_) external view returns (uint128, uint128, bool) { Trader memory trader = traders[address_]; if (trader.trader_id == 0) { trader.claimable = true; // true by default } return (trader.token_x, trader.token_y, trader.claimable); } /// @notice Allows the administrator to change the market maker address /// @param _marketmaker The new address of the market maker /// @param _should_invoke_on_trade Flag indicating that the market maker must implement ITradeConsumer /// @param _admin_commission_rate The commission rate for the administrator /// @dev If the market maker address is null, it can be set by anyone function changeMarketMaker( address _marketmaker, bool _should_invoke_on_trade, uint64 _admin_commission_rate ) external nonReentrant { address administrator = owner(); require(msg.sender == administrator, Errors.Forbidden()); _transferFees(); require(_admin_commission_rate <= 1e18, Errors.InvalidCommissionRate()); admin_commission_rate = _admin_commission_rate; address marketmaker = marketmaker_config.marketmaker; if (marketmaker != _marketmaker) { emit MarketMakerChanged(_marketmaker, marketmaker); } _changeMarketMaker(_marketmaker, _should_invoke_on_trade); } /// @notice The new owner accepts the ownership transfer. function acceptOwnership() public override nonReentrant { _transferFees(); super.acceptOwnership(); } /// @notice Sets the claimable status for the trader calling the function /// @param status The new claimable status function setClaimableStatus(bool status) external nonReentrant whenNotPaused { _getOrCreateTraderId(msg.sender); traders[msg.sender].claimable = status; emit ClaimableStatusChanged(msg.sender, status); } /// @param isAsk Indicates if the order is a sell order (true) or a buy order (false) /// @param quantity The amount of tokens to order divided by the scaling factor. This amount would be multiplied by the scaling factor inside the function /// @param price The price per token in the order, no more than 6 significant digits /// @param max_commission The maximum commission, which may include passive and/or aggressive fee /// @param market_only Indicates if the order should be executed only against existing orders in the market /// @param post_only Indicates if the order should be posted only and not executed immediately /// @param transfer_executed_tokens Flag for transferring executed tokens (true) or crediting them to the balance (false) /// @param expires The time at which the order will expire /// @return order_id The identifier of the created order /// @return executed_shares Number of executed shares /// @return executed_value Executed value /// @return aggressive_fee Aggressive fee function placeOrder( bool isAsk, uint128 quantity, uint72 price, uint128 max_commission, bool market_only, bool post_only, bool transfer_executed_tokens, uint256 expires ) public payable ensure(expires) whenNotPaused returns ( uint64 order_id, uint128 executed_shares, uint128 executed_value, uint128 aggressive_fee ) { ExecutionResult memory result = _placeOrder( isAsk, quantity, price, max_commission, market_only, post_only, transfer_executed_tokens ); order_id = result.order_id; executed_shares = result.executed_shares; executed_value = result.executed_value; aggressive_fee = result.aggressive_fee; _invokeTradeConsumerCallback(result.executed_shares, isAsk); } /// @param isAsk Indicates if the order is a sell order (true) or a buy order (false) /// @param quantity The amount of tokens to order divided by the scaling factor. This amount would be multiplied by the scaling factor inside the function /// @param price The price per token in the order, no more than 6 significant digits /// @param max_commission The maximum commission, which may include passive and/or aggressive fee /// @param amount_to_approve The amount of tokens to approve divided by the scaling factor. This amount would be multiplied by the scaling factor inside the function /// @param market_only Indicates if the order should be executed only against existing orders in the market /// @param post_only Indicates if the order should be posted only and not executed immediately /// @param transfer_executed_tokens Flag for transferring executed tokens (true) or crediting them to the balance (false) /// @param expires The time at which the order will expire /// @param v The component V of the signature /// @param r The component R of the signature /// @param s The component S of the signature /// @return order_id The identifier of the created order /// @return executed_shares Number of executed shares /// @return executed_value Executed value /// @return aggressive_fee Aggressive fee function placeOrder( bool isAsk, uint128 quantity, uint72 price, uint128 max_commission, uint128 amount_to_approve, bool market_only, bool post_only, bool transfer_executed_tokens, uint256 expires, uint8 v, bytes32 r, bytes32 s ) public payable ensure(expires) whenNotPaused returns ( uint64 order_id, uint128 executed_shares, uint128 executed_value, uint128 aggressive_fee ) { address token_address = isAsk ? address(token_x) : address(token_y); IERC20Permit token = IERC20Permit(token_address); uint256 value = isAsk ? amount_to_approve * scaling_factor_token_x : amount_to_approve * scaling_factor_token_y; try token.permit(msg.sender, address(this), value, expires, v, r, s) {} catch {} ExecutionResult memory result = _placeOrder( isAsk, quantity, price, max_commission, market_only, post_only, transfer_executed_tokens ); order_id = result.order_id; executed_shares = result.executed_shares; executed_value = result.executed_value; aggressive_fee = result.aggressive_fee; _invokeTradeConsumerCallback(result.executed_shares, isAsk); } /// @notice Places a market order with a target token Y /// @param isAsk Order direction: true for sell (ask), false for buy (bid) /// @param target_token_y_value Target value of token Y for execution /// @param price Order price /// @param max_commission Maximum commission /// @param transfer_executed_tokens Flag for transferring executed tokens /// @param expires Time when the order expires /// @return executed_shares Number of executed shares /// @return executed_value Executed value /// @return aggressive_fee Aggressive fee function placeMarketOrderWithTargetValue( bool isAsk, uint128 target_token_y_value, uint72 price, uint128 max_commission, bool transfer_executed_tokens, uint256 expires ) public payable ensure(expires) whenNotPaused returns ( uint128 executed_shares, uint128 executed_value, uint128 aggressive_fee ) { uint24 packed_price = FP24.packFP24(price); uint64 price_id = _genPriceId(packed_price, isAsk); uint128 order_quantity; uint128 total_fees_and_payout_rate = total_aggressive_commission_rate + passive_order_payout_rate; if (isAsk) { uint128 adjusted_token_y_value = uint256(target_token_y_value).mulDivDown( wad, wad - total_fees_and_payout_rate ).toUint128(); (order_quantity, ) = bidTrie.previewExecuteRight( price_id, type(uint128).max, adjusted_token_y_value ); } else { uint128 adjusted_token_y_value = uint256(target_token_y_value).mulDivDown( wad, wad + total_fees_and_payout_rate ).toUint128(); (order_quantity, ) = askTrie.previewExecuteRight( price_id, type(uint128).max, adjusted_token_y_value ); } ExecutionResult memory result = _placeOrder( isAsk, order_quantity, price, max_commission, true, // market_only false, // post_only transfer_executed_tokens ); executed_shares = result.executed_shares; executed_value = result.executed_value; aggressive_fee = result.aggressive_fee; _invokeTradeConsumerCallback(result.executed_shares, isAsk); } /// @notice Places a market order with a target token Y value using EIP-2612 permit /// @param isAsk Order direction: true for sell (ask), false for buy (bid) /// @param target_token_y_value Target value of token Y for execution /// @param price Order price /// @param max_commission Maximum commission /// @param amount_to_approve The amount of tokens to approve divided by the scaling factor. This amount would be multiplied by the scaling factor inside the function /// @param transfer_executed_tokens Flag for transferring executed tokens /// @param expires Time when the order expires /// @param v Signature component v /// @param r Signature component r /// @param s Signature component s /// @return executed_shares Number of executed shares /// @return executed_value Executed value /// @return aggressive_fee Aggressive fee function placeMarketOrderWithTargetValue( bool isAsk, uint128 target_token_y_value, uint72 price, uint128 max_commission, uint128 amount_to_approve, bool transfer_executed_tokens, uint256 expires, uint8 v, bytes32 r, bytes32 s ) external payable ensure(expires) whenNotPaused returns ( uint128 executed_shares, uint128 executed_value, uint128 aggressive_fee ) { address token_address = isAsk ? address(token_x) : address(token_y); IERC20Permit token = IERC20Permit(token_address); uint256 value = isAsk ? amount_to_approve * scaling_factor_token_x : amount_to_approve * scaling_factor_token_y; try token.permit(msg.sender, address(this), value, expires, v, r, s) {} catch {} return placeMarketOrderWithTargetValue( isAsk, target_token_y_value, price, max_commission, transfer_executed_tokens, expires ); } /// @notice Allows a trader to claim or fully cancel the order /// @param order_id The identifier of the order to claim /// @param only_claim A flag indicating that only the executed part of the order should be sent /// without unnecessarily removing the order. /// @param transfer_tokens If true, transfers the tokens to the trader's address /// @param expires The time at which the order will expire function claimOrder( uint64 order_id, bool only_claim, bool transfer_tokens, uint256 expires ) public ensure(expires) nonReentrant whenNotPaused { _calculateAndSendOrderPayout(msg.sender, order_id, only_claim, transfer_tokens); } /// @notice Allows batch claiming of orders for multiple addresses /// @param addresses Array of trader addresses claiming orders /// @param order_ids Array of order IDs corresponding to trader addresses /// @param only_claim A flag indicating that only the executed part of the order should be sent /// without unnecessarily removing the order. /// @param expires The time at which the order will expire function batchClaim( address[] memory addresses, uint64[] memory order_ids, bool only_claim, uint256 expires ) external ensure(expires) nonReentrant whenNotPaused { require(addresses.length == order_ids.length, Errors.ArrayLengthMismatch()); for (uint i = 0; i < addresses.length; i++) { _calculateAndSendOrderPayout(addresses[i], order_ids[i], only_claim, true); } } /// @notice Claiming/canceling an existing order and creating the new one with the same (bid/ask) direction /// @param old_order_id The identifier of the order to modify /// @param new_quantity The amount of tokens for the new order /// @param new_price The price per token for new order, no more than 6 significant digits /// @param max_commission The maximum commission, which may include passive and/or aggressive fee /// @param post_only Indicates if the order should be posted only and not executed immediately /// @param transfer_tokens If true, tokens will be transferred to the order owner /// @param expires The time at which the order will expire function changeOrder( uint64 old_order_id, uint128 new_quantity, uint72 new_price, uint128 max_commission, bool post_only, bool transfer_tokens, uint256 expires ) public whenNotPaused returns (uint64 order_id) { if (old_order_id > 0x1) { claimOrder(old_order_id, false, transfer_tokens, expires); } if (new_quantity > 0) { bool isAsk = (old_order_id & uint64(0x1)) == 0x1; (order_id, , , ) = placeOrder( isAsk, new_quantity, new_price, max_commission, false, post_only, transfer_tokens, expires ); } } /// @notice Allows batch placing or changing of orders for multiple addresses /// @param order_ids Array of order IDs or directions corresponding to orders /// @param quantities Array of amounts of tokens for the new orders /// @param prices Array of prices per token for new orders, no more than 6 significant digits for every price /// @param max_commission_per_order The maximum commission per order, which may include passive and/or aggressive fee /// @param post_only Indicates if the order should be posted only and not executed immediately /// @param transfer_tokens If true, tokens will be transferred to the order owners /// @param expires The time at which the order will expire /// @return new_order_ids Array of new order IDs function batchChangeOrder( uint64[] memory order_ids, uint128[] memory quantities, uint72[] memory prices, uint128 max_commission_per_order, bool post_only, bool transfer_tokens, uint256 expires ) external ensure(expires) whenNotPaused returns (uint64[] memory new_order_ids) { require( order_ids.length == quantities.length && order_ids.length == prices.length, Errors.ArrayLengthMismatch() ); new_order_ids = new uint64[](order_ids.length); for (uint i = 0; i < order_ids.length; i++) { new_order_ids[i] = changeOrder( order_ids[i], quantities[i], prices[i], max_commission_per_order, post_only, transfer_tokens, expires ); } return new_order_ids; } /// @notice Deposits the specified amounts of token X and token Y into the trader's balance on the contract /// @param token_x_amount The amount of token X to deposit /// @param token_y_amount The amount of token Y to deposit function depositTokens( uint128 token_x_amount, uint128 token_y_amount ) public nonReentrant whenNotPaused { uint256 actual_token_x_to_receive = 0; uint256 actual_token_y_to_receive = 0; if (token_x_amount > 0) { traders[msg.sender].token_x += token_x_amount; actual_token_x_to_receive = _convertToActualTokenXAmount(token_x_amount); } if (token_y_amount > 0) { traders[msg.sender].token_y += token_y_amount; actual_token_y_to_receive = _convertToActualTokenYAmount(token_y_amount); } // actual erc20 transactions if (actual_token_x_to_receive > 0) { _safeTansferFromWithBalanceCheck(token_x, msg.sender, address(this), actual_token_x_to_receive); } if (actual_token_y_to_receive > 0) { _safeTansferFromWithBalanceCheck(token_y, msg.sender, address(this), actual_token_y_to_receive); } emit Deposited(msg.sender, token_x_amount, token_y_amount); } /// @notice Deposits the specified amounts of token X and token Y into the trader's balance on the contract /// @param token_x_amount The amount of token X to deposit /// @param token_y_amount The amount of token Y to deposit /// @param v_x The component V of the signature for token X /// @param r_x The component R of the signature for token X /// @param s_x The component S of the signature for token X /// @param v_y The component V of the signature for token Y /// @param r_y The component R of the signature for token Y /// @param s_y The component S of the signature for token Y /// @param expires The time at which the signatures will expire function depositTokens( uint128 token_x_amount, uint128 token_y_amount, uint8 v_x, bytes32 r_x, bytes32 s_x, uint8 v_y, bytes32 r_y, bytes32 s_y, uint256 expires ) external whenNotPaused { if (token_x_amount > 0) { IERC20Permit token_x_permit = IERC20Permit(address(token_x)); try token_x_permit.permit( msg.sender, address(this), token_x_amount * scaling_factor_token_x, expires, v_x, r_x, s_x ) {} catch {} } if (token_y_amount > 0) { IERC20Permit token_y_permit = IERC20Permit(address(token_y)); try token_y_permit.permit( msg.sender, address(this), token_y_amount * scaling_factor_token_y, expires, v_y, r_y, s_y ) {} catch {} } depositTokens(token_x_amount, token_y_amount); } /// @notice Withdraws specified amounts of token X and token Y from the trader's balance on the contract /// @param withdraw_all If set to true, withdraws all the trader's tokens; otherwise, uses the specified amounts /// @param token_x_amount The amount of token X to withdraw (ignored if withdraw_all = true) /// @param token_y_amount The amount of token Y to withdraw (ignored if withdraw_all = true) function withdrawTokens( bool withdraw_all, uint128 token_x_amount, uint128 token_y_amount ) external nonReentrant whenNotPaused { uint256 actual_token_x_to_send = 0; uint256 actual_token_y_to_send = 0; uint128 clients_shares = traders[msg.sender].token_x; uint128 clients_value = traders[msg.sender].token_y; if (withdraw_all) { token_x_amount = clients_shares; token_y_amount = clients_value; } if (token_x_amount > 0) { require(clients_shares >= token_x_amount, Errors.InsufficientTokenXBalance()); unchecked { traders[msg.sender].token_x = clients_shares - token_x_amount; } actual_token_x_to_send = _convertToActualTokenXAmount(token_x_amount); } if (token_y_amount > 0) { require(clients_value >= token_y_amount, Errors.InsufficientTokenYBalance()); unchecked { traders[msg.sender].token_y = clients_value - token_y_amount; } actual_token_y_to_send = _convertToActualTokenYAmount(token_y_amount); } // actual erc20 transactions if (actual_token_x_to_send > 0) { token_x.safeTransfer(msg.sender, actual_token_x_to_send); } if (actual_token_y_to_send > 0) { token_y.safeTransfer(msg.sender, actual_token_y_to_send); } emit Withdrawn(msg.sender, token_x_amount, token_y_amount); } /// @notice Returns the accumulated fees. /// @return The actual accumulated fees. function getAccumulatedFees() external view returns (uint256) { return (accumulated_fees - 1); } /// @notice Transfers the accumulated commissions to the administrator and marketmaker. function transferFees() external whenNotPaused { _transferFees(); } /// @notice Pause contract /// @dev Can be called by administrator and pauser function pause() external { require(msg.sender == owner() || msg.sender == pauser, Errors.Forbidden()); _pause(); } /// @notice Unpause contract /// @dev Can be called by administrator function unpause() external onlyOwner { _unpause(); } /// @notice Change pauser by administrator /// @param pauser_ New pauser address /// @dev Can be called only by administrator function changePauser(address pauser_) external onlyOwner { if (pauser == pauser_) { return; } emit PauserChanged(pauser_, pauser); pauser = pauser_; } /// @notice Extracts the direction and price from the given order ID. /// @param order_id The unique identifier of the order. /// @return isAsk A boolean indicating if the order is an ask (true) or a bid (false). /// @return price The price of the order. function _extractDirectionAndPrice(uint64 order_id) internal pure returns (bool isAsk, uint72 price) { // Orders with an order_id ending in 1 are asks, and those ending in 0 are bids. isAsk = (order_id & uint64(0x1)) == 0x1; uint24 packed_price = uint24(order_id >> (nonce_length + 1)); if (isAsk) { unchecked{ packed_price = type(uint24).max - packed_price; } } price = FP24.unPackFP24(packed_price); } function _authorizeUpgrade(address) internal override onlyOwner {} /// @param isAsk Indicates if the order is a sell order (true) or a buy order (false) /// @param quantity The amount of tokens to order divided by the scaling factor. This amount would be multiplied by the scaling factor inside the function /// @param price The price per token in the order, no more than 6 significant digits /// @param max_commission The maximum commission, which may include passive and/or aggressive fee /// @param market_only Indicates if the order should be executed only against existing orders in the market /// @param post_only Indicates if the order should be posted only and not executed immediately /// @param transfer_executed_tokens Flag for transferring executed tokens (true) or crediting them to the balance (false) /// @return execution_result ExecutionResult structure containing information about the executed order function _placeOrder( bool isAsk, uint128 quantity, uint72 price, uint128 max_commission, bool market_only, bool post_only, bool transfer_executed_tokens ) internal nonReentrant returns (ExecutionResult memory execution_result) { require(!market_only || !post_only, Errors.MarketOnlyAndPostOnlyFlagsConflict()); require(quantity != 0 && price != 0, Errors.ZeroTokenTransferNotAllowed()); require( msg.value == 0 || (supports_native_eth && (isAsk == is_token_x_weth)), Errors.NativeETHDisabled() ); uint24 packed_price = FP24.packFP24(price); uint64 price_id = _genPriceId(packed_price, isAsk); if (post_only) { bool aggressive_trade = false; if (isAsk) { if (price_id <= bidTrie.best_offer()) { aggressive_trade = true; } } else { if (price_id <= askTrie.best_offer()) { aggressive_trade = true; } } if (aggressive_trade) { if (msg.value > 0) { _sendETH(msg.sender, msg.value); } emit OrderPlaced( msg.sender, 0x0, // order_id isAsk, quantity, price, 0, // passive_shares, 0, // passive_fee 0, // executed_shares 0, // executed_value 0, // aggressive_fee false, // market_only, true // post_only ); return execution_result; } } uint128 x_to_send; uint128 y_to_send; uint128 x_to_receive; uint128 y_to_receive; // processing aggressive part uint128 executed_shares; uint128 executed_value; uint128 aggressive_fee; if (!post_only) { if (isAsk) { (executed_shares, executed_value) = bidTrie.executeRight(price_id, quantity); x_to_receive = executed_shares; y_to_send = executed_value; } else { (executed_shares, executed_value) = askTrie.executeRight(price_id, quantity); x_to_send = executed_shares; y_to_receive = executed_value; } aggressive_fee = _calculateAndTransferTotalAggressiveFeesAndPayout(executed_value); y_to_receive += aggressive_fee; if (executed_shares > 0){ require(watch_dog.isChainStable(), Errors.ChainIsUnstableForTrades()); } execution_result.executed_shares = executed_shares; execution_result.executed_value = executed_value; execution_result.aggressive_fee = aggressive_fee; } // processing passive part uint64 order_id; uint128 passive_shares = !market_only ? (quantity - executed_shares) : 0; uint128 passive_fee; if (passive_shares > 0) { order_id = _genOrderId(packed_price, isAsk); uint64 trader_id = _getOrCreateTraderId(msg.sender); uint128 total_value = passive_shares * price; passive_fee = _calculateTotalPassiveCommission(total_value); if (isAsk) { askTrie.addOrder(trader_id, order_id, passive_shares, total_value); x_to_receive += passive_shares; } else { bidTrie.addOrder(trader_id, order_id, passive_shares, total_value); // Orders with an order_id ending in 1 are asks, and those ending in 0 are bids. order_id ^= 0x1; y_to_receive += total_value + passive_fee; } execution_result.order_id = order_id; } require(passive_fee + aggressive_fee <= max_commission, Errors.MaxCommissionFailure()); emit OrderPlaced( msg.sender, order_id, isAsk, quantity, price, passive_shares, passive_fee, executed_shares, executed_value, aggressive_fee, market_only, post_only ); // actual token transfer _handleTokenTransfer( msg.sender, transfer_executed_tokens, x_to_send, x_to_receive, y_to_send, y_to_receive ); } /// @notice Change market maker address and should invoke on trade flag /// @param _marketmaker New market maker address /// @param _should_invoke_on_trade Flag indicating that the market maker must implement ITradeConsumer function _changeMarketMaker( address _marketmaker, bool _should_invoke_on_trade ) internal { if (_should_invoke_on_trade) { IERC165 maker = IERC165(_marketmaker); if (!maker.supportsInterface(type(ITradeConsumer).interfaceId)) { revert Errors.InvalidMarketMaker(); } } require(_marketmaker != address(0), Errors.AddressIsZero()); marketmaker_config = MarketMakerConfig ({ marketmaker: _marketmaker, should_invoke_on_trade: _should_invoke_on_trade }); } /// @notice Transfers the accumulated commissions to the administrator and marketmaker. function _transferFees() internal { uint256 total_fees = (accumulated_fees - 1) / wad; accumulated_fees -= total_fees * wad; if (total_fees == 0) { return; } address administrator = owner(); uint256 admin_fees = total_fees.mulWadUp(admin_commission_rate); uint256 marketmaker_fees = total_fees - admin_fees; if (marketmaker_fees > 0) { traders[marketmaker_config.marketmaker].token_y += marketmaker_fees.toUint128(); } uint256 actual_token_y_to_send = _convertToActualTokenYAmount(admin_fees.toUint128()); if (actual_token_y_to_send > 0){ token_y.safeTransfer(administrator, actual_token_y_to_send); } } /// @notice Retrieves or creates a trader ID for a given address. /// @param trader_address The address of the trader for whom the ID is to be retrieved or created. /// @return trader_id The trader ID associated with the given address. function _getOrCreateTraderId(address trader_address) internal returns (uint64 trader_id) { trader_id = traders[trader_address].trader_id; if (trader_id == 0) { // initialize a new Trader structure trader_id = ++last_used_trader_id; traders[trader_address].trader_id = trader_id; traders[trader_address].claimable = true; } } /// @notice Calculates and transfers the total fees and payout. /// @param executed_value The value of the executed order. /// @return The total aggressive fees calculated and transferred. function _calculateAndTransferTotalAggressiveFeesAndPayout(uint128 executed_value) internal returns (uint128) { if (executed_value == 0) { return 0; } uint128 total_fees_and_payout_rate = total_aggressive_commission_rate + passive_order_payout_rate; if (total_fees_and_payout_rate == 0) { return 0; } uint256 total_aggressive_fees_and_payout = uint256(executed_value).mulWadUp( total_fees_and_payout_rate ); accumulated_fees += ( total_aggressive_fees_and_payout * wad - executed_value * uint256(passive_order_payout_rate) + executed_value * uint256(total_passive_commission_rate) ); return total_aggressive_fees_and_payout.toUint128(); } /// @notice Calculates the total passive commission for a given value. /// @param total_value The total value for which the passive commission is to be calculated. /// @return The total passive commission calculated. function _calculateTotalPassiveCommission(uint128 total_value) internal view returns (uint128) { if (total_passive_commission_rate == 0){ return 0; } uint256 total_passive_commissions = uint256(total_value).mulWadUp(total_passive_commission_rate); return total_passive_commissions.toUint128(); } /// @notice Calculates the passive order payout or refunded commissions based on the remaining shares. /// @param isAsk A boolean flag indicating whether the order is an ask (true) or a bid (false). /// @param price The price of the order. /// @param remain_shares The remaining shares of the order. /// @param total_shares The total shares of the order. /// @return refund_value The calculated passive payout or refunded commissions. /// @return fee_rounding_error The rounding error in the fee calculation. function _calculatePassiveOrderPayoutOrRefundedCommissions( bool isAsk, uint72 price, uint128 remain_shares, uint128 total_shares ) internal view returns(uint128 refund_value, uint256 fee_rounding_error) { if (passive_order_payout_rate > 0) { uint256 executed_value = price * (total_shares - remain_shares); uint256 passive_payout = executed_value.mulWadDown(passive_order_payout_rate); refund_value = passive_payout.toUint128(); fee_rounding_error = executed_value * passive_order_payout_rate - refund_value * wad; } else { // Refunding part of the passive commission. uint128 executed_value = price * (total_shares - remain_shares); uint256 executed_fees = _calculateTotalPassiveCommission(executed_value); fee_rounding_error = executed_fees * wad - executed_value * total_passive_commission_rate; if (!isAsk) { uint128 total_value = price * total_shares; uint128 total_fees = _calculateTotalPassiveCommission(total_value); refund_value = total_fees - executed_fees.toUint128(); } } } /// @notice Decrements the nonce and returns the new value, reverts if nonce reaches zero. /// @dev This function is used to ensure unique order identifiers by decrementing the nonce. /// If the nonce reaches zero, the function will revert to prevent identifier collisions. /// @return c_nonce The decremented nonce value. function _getAndUpdateNonce() internal returns (uint64 c_nonce) { c_nonce = nonce; unchecked { nonce -= 1; } require(nonce > 0, Errors.NonceExhaustedFailure()); } /// @notice Generates a unique price identifier based on the given price and order type. /// @param packed_price The FP2 price of the order. /// @param isAsk A boolean indicating whether the order is an ask (true) or a bid (false). /// @return price_id The generated unique identifier for the price. function _genPriceId(uint24 packed_price, bool isAsk) internal pure returns (uint64 price_id) { if (isAsk) { price_id = uint64(packed_price) << nonce_length; } else { uint64 max_price = type(uint24).max; unchecked { price_id = (max_price - packed_price) << nonce_length; } } price_id = price_id << 1 ^ 0x1; } /// @notice Generates a unique order identifier based on the price and order type. /// @param packed_price The FP24 price of the order. /// @param isAsk A boolean indicating whether the order is an ask (true) or a bid (false). /// @return order_id The generated unique identifier for the order. function _genOrderId(uint24 packed_price, bool isAsk) internal returns (uint64 order_id) { uint64 c_nonce = _getAndUpdateNonce(); if (isAsk) { unchecked { order_id = ((uint64(type(uint24).max - packed_price) << nonce_length) | c_nonce); } } else { order_id = ((uint64(packed_price) << nonce_length) | c_nonce); } order_id = order_id << 1 ^ 0x1; } /// @notice Converts the amount of token X from a simplified representation to the actual ERC20 amount. /// @dev Multiplies the amount of token X by the scaling factor to obtain the actual amount. /// @param token The amount of token X in a simplified representation. /// @return Returns the actual amount of token X after scaling. function _convertToActualTokenXAmount(uint128 token) internal view returns (uint256) { return token * scaling_factor_token_x; } /// @notice Converts the amount of token Y from a simplified representation to the actual ERC20 amount. /// @dev Multiplies the amount of token Y by the scaling factor to obtain the actual amount. /// @param token The amount of token Y in a simplified representation. /// @return Returns the actual amount of token Y after scaling. function _convertToActualTokenYAmount(uint128 token) internal view returns (uint256) { return token * scaling_factor_token_y; } /// @dev Calculates the payout for an order and, if necessary, transfers the tokens. /// @param owner The owner of the order for which the payout is being calculated. /// @param order_id The identifier of the order for which the payout is being calculated. /// @param only_claim A flag indicating that only the executed part of the order should be sent /// without unnecessarily removing the order. /// @param transfer_tokens If true, tokens will be transferred to the order owner. function _calculateAndSendOrderPayout( address owner, uint64 order_id, bool only_claim, bool transfer_tokens ) internal { uint64 trader_id = _getOrCreateTraderId(owner); require(traders[owner].claimable || (msg.sender == owner), Errors.ClaimNotAllowed()); (bool isAsk, uint72 price) = _extractDirectionAndPrice(order_id); uint128 x_to_send; uint128 y_to_send; uint128 total_shares; uint128 remain_shares; uint128 order_shares_remaining = 0; if (isAsk) { if (only_claim) { uint128 executed_shares; (executed_shares, order_shares_remaining) = askTrie.claimExecuted(order_id, trader_id); total_shares = executed_shares; remain_shares = 0; } else { (total_shares, remain_shares) = askTrie.removeOrder(order_id, trader_id); } uint128 executed_value = (total_shares - remain_shares) * price; uint128 fees = _calculateTotalPassiveCommission(executed_value); x_to_send = remain_shares; y_to_send = executed_value - fees; } else { if (only_claim) { uint128 executed_shares; (executed_shares, order_shares_remaining) = bidTrie.claimExecuted(order_id|0x1, trader_id); total_shares = executed_shares; remain_shares = 0; } else { (total_shares, remain_shares) = bidTrie.removeOrder(order_id|0x1, trader_id); } x_to_send = total_shares - remain_shares; y_to_send = remain_shares * price; } (uint128 passive_payout, uint256 fee_rounding_error) = _calculatePassiveOrderPayoutOrRefundedCommissions( isAsk, price, remain_shares, total_shares ); emit OrderClaimed(order_id, order_shares_remaining, x_to_send, y_to_send, passive_payout, only_claim); y_to_send += passive_payout; accumulated_fees += fee_rounding_error; require((remain_shares == 0) || (msg.sender == owner), Errors.OnlyOwnerCanCancelOrders()); _handleTokenTransfer(owner, transfer_tokens, x_to_send, 0, y_to_send, 0); } /// @dev Handles the transfer of tokens during the execution or claiming/cancelling of an order. /// @param client The address of the trader executing the order. /// @param transfer_tokens A boolean flag indicating whether to transfer the tokens immediately. /// @param x_to_send The amount of token X to send. /// @param x_to_receive The amount of token X to receive. /// @param y_to_send The amount of token Y to send. /// @param y_to_receive The amount of token Y to receive. function _handleTokenTransfer( address client, bool transfer_tokens, uint128 x_to_send, uint128 x_to_receive, uint128 y_to_send, uint128 y_to_receive ) internal { uint256 actual_token_x_to_send = 0; uint256 actual_token_x_to_receive = 0; uint256 actual_token_y_to_send = 0; uint256 actual_token_y_to_receive = 0; IWETH weth = is_token_x_weth ? IWETH(address(token_x)) : IWETH(address(token_y)); if (msg.value > 0) { if (is_token_x_weth) { uint128 extra_x = (msg.value / scaling_factor_token_x).toUint128(); uint256 actual_value = _convertToActualTokenXAmount(extra_x); x_to_send += extra_x; uint256 rounded_value = msg.value - actual_value; actual_token_x_to_send = rounded_value; } else { uint128 extra_y = (msg.value / scaling_factor_token_y).toUint128(); uint256 actual_value = _convertToActualTokenYAmount(extra_y); y_to_send += extra_y; uint256 rounded_value = msg.value - actual_value; actual_token_y_to_send = rounded_value; } } // processing token_x if (x_to_send > x_to_receive) { uint128 shares_to_send; unchecked { shares_to_send = x_to_send - x_to_receive; } if (transfer_tokens) { actual_token_x_to_send += _convertToActualTokenXAmount(shares_to_send); } else { traders[client].token_x += shares_to_send; emit Deposited(client, shares_to_send, 0); } } else if (x_to_send < x_to_receive) { uint128 shares_to_receive; unchecked { shares_to_receive = x_to_receive - x_to_send; } uint128 clients_shares = traders[client].token_x; if (clients_shares >= shares_to_receive) { unchecked { traders[client].token_x -= shares_to_receive; } emit Withdrawn(client, shares_to_receive, 0); } else { unchecked { shares_to_receive -= clients_shares; } actual_token_x_to_receive = _convertToActualTokenXAmount(shares_to_receive); traders[client].token_x = 0; emit Withdrawn(client, clients_shares, 0); } } // processing token_y if (y_to_send > y_to_receive) { uint128 value_to_send; unchecked { value_to_send = y_to_send - y_to_receive; } if (transfer_tokens) { actual_token_y_to_send += _convertToActualTokenYAmount(value_to_send); } else { traders[client].token_y += value_to_send; emit Deposited(client, 0, value_to_send); } } else if (y_to_send < y_to_receive) { uint128 value_to_receive; unchecked { value_to_receive = y_to_receive - y_to_send; } uint128 clients_value = traders[client].token_y; if (clients_value >= value_to_receive) { unchecked { traders[client].token_y -= value_to_receive; } emit Withdrawn(client, 0, value_to_receive); } else { unchecked { value_to_receive -= clients_value; } actual_token_y_to_receive = _convertToActualTokenYAmount(value_to_receive); traders[client].token_y = 0; emit Withdrawn(client, 0, clients_value); } } // Withdrawing WETH if (supports_native_eth) { uint256 value_to_withdraw; if (is_token_x_weth && (actual_token_x_to_send > address(this).balance)) { value_to_withdraw = actual_token_x_to_send - address(this).balance; } if (!is_token_x_weth && (actual_token_y_to_send > address(this).balance)) { value_to_withdraw = actual_token_y_to_send - address(this).balance; } if (value_to_withdraw > 0) { weth.withdraw(value_to_withdraw); } } // actual erc20 transactions if (actual_token_x_to_send > 0) { if (supports_native_eth && is_token_x_weth) { _sendETH(client, actual_token_x_to_send); } else { token_x.safeTransfer(client, actual_token_x_to_send); } } if (actual_token_x_to_receive > 0) { _safeTansferFromWithBalanceCheck(token_x, client, address(this), actual_token_x_to_receive); } if (actual_token_y_to_send > 0) { if (supports_native_eth && !is_token_x_weth) { _sendETH(client, actual_token_y_to_send); } else { token_y.safeTransfer(client, actual_token_y_to_send); } } if (actual_token_y_to_receive > 0) { _safeTansferFromWithBalanceCheck(token_y, client, address(this), actual_token_y_to_receive); } // Depositing WETH if (address(this).balance > 0) { weth.deposit{value: address(this).balance}(); } } /// @dev Transfer tokens safely with balance check /// @param token Token contract /// @param from The address from which tokens are sent /// @param to The address to which tokens are sent /// @param value Amount of tokens function _safeTansferFromWithBalanceCheck(IERC20 token, address from, address to, uint256 value) internal { uint256 balance_before = token.balanceOf(address(this)); token.safeTransferFrom(from, to, value); uint256 balance_after = token.balanceOf(address(this)); require(balance_after - balance_before == value, Errors.InvalidTransfer()); } /// @notice Sends ETH to the specified address /// @dev Uses a low-level call to send ETH, which allows bypassing the 2300 gas limit imposed by transfer function /// @param to The recipient address for ETH /// @param value The amount of ETH to send (in wei) function _sendETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(""); require(success, Errors.TransferFailed()); } /// @dev Invoke TradeConsumer onTrade callback if executed shares are greater than zero, msg.sender is not /// market maker and should_invoke_on_trade is true /// @param executed_shares Executed shares /// @param isAsk A boolean indicating whether the order is an ask (true) or a bid (false) function _invokeTradeConsumerCallback(uint128 executed_shares, bool isAsk) internal { if (executed_shares == 0) return; if (marketmaker_config.should_invoke_on_trade && msg.sender != marketmaker_config.marketmaker) { ITradeConsumer(marketmaker_config.marketmaker).onTrade(isAsk); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {OwnableUpgradeable} from "./OwnableUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable2Step struct Ownable2StepStorage { address _pendingOwner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable2Step")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant Ownable2StepStorageLocation = 0x237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00; function _getOwnable2StepStorage() private pure returns (Ownable2StepStorage storage $) { assembly { $.slot := Ownable2StepStorageLocation } } event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); function __Ownable2Step_init() internal onlyInitializing { } function __Ownable2Step_init_unchained() internal onlyInitializing { } /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); return $._pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); $._pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { Ownable2StepStorage storage $ = _getOwnable2StepStorage(); delete $._pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract PausableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Pausable struct PausableStorage { bool _paused; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300; function _getPausableStorage() private pure returns (PausableStorage storage $) { assembly { $.slot := PausableStorageLocation } } /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); /** * @dev The operation failed because the contract is paused. */ error EnforcedPause(); /** * @dev The operation failed because the contract is not paused. */ error ExpectedPause(); /** * @dev Initializes the contract in unpaused state. */ function __Pausable_init() internal onlyInitializing { __Pausable_init_unchained(); } function __Pausable_init_unchained() internal onlyInitializing { PausableStorage storage $ = _getPausableStorage(); $._paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { PausableStorage storage $ = _getPausableStorage(); return $._paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { if (paused()) { revert EnforcedPause(); } } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { if (!paused()) { revert ExpectedPause(); } } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { PausableStorage storage $ = _getPausableStorage(); $._paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant NOT_ENTERED = 1; uint256 private constant ENTERED = 2; /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard struct ReentrancyGuardStorage { uint256 _status; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) { assembly { $.slot := ReentrancyGuardStorageLocation } } /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); $._status = NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // On the first call to nonReentrant, _status will be NOT_ENTERED if ($._status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail $._status = ENTERED; } function _nonReentrantAfter() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) $._status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); return $._status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^0.8.20; /** * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow * checks. * * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can * easily result in undesired exploitation or bugs, since developers usually * assume that overflows raise errors. `SafeCast` restores this intuition by * reverting the transaction when such an operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(uint256 value); /** * @dev Returns the downcasted uint248 from uint256, reverting on * overflow (when the input is greater than largest uint248). * * Counterpart to Solidity's `uint248` operator. * * Requirements: * * - input must fit into 248 bits */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(value); } /** * @dev Returns the downcasted uint240 from uint256, reverting on * overflow (when the input is greater than largest uint240). * * Counterpart to Solidity's `uint240` operator. * * Requirements: * * - input must fit into 240 bits */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(value); } /** * @dev Returns the downcasted uint232 from uint256, reverting on * overflow (when the input is greater than largest uint232). * * Counterpart to Solidity's `uint232` operator. * * Requirements: * * - input must fit into 232 bits */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(value); } /** * @dev Returns the downcasted uint224 from uint256, reverting on * overflow (when the input is greater than largest uint224). * * Counterpart to Solidity's `uint224` operator. * * Requirements: * * - input must fit into 224 bits */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(value); } /** * @dev Returns the downcasted uint216 from uint256, reverting on * overflow (when the input is greater than largest uint216). * * Counterpart to Solidity's `uint216` operator. * * Requirements: * * - input must fit into 216 bits */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(value); } /** * @dev Returns the downcasted uint208 from uint256, reverting on * overflow (when the input is greater than largest uint208). * * Counterpart to Solidity's `uint208` operator. * * Requirements: * * - input must fit into 208 bits */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(value); } /** * @dev Returns the downcasted uint200 from uint256, reverting on * overflow (when the input is greater than largest uint200). * * Counterpart to Solidity's `uint200` operator. * * Requirements: * * - input must fit into 200 bits */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(value); } /** * @dev Returns the downcasted uint192 from uint256, reverting on * overflow (when the input is greater than largest uint192). * * Counterpart to Solidity's `uint192` operator. * * Requirements: * * - input must fit into 192 bits */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(value); } /** * @dev Returns the downcasted uint184 from uint256, reverting on * overflow (when the input is greater than largest uint184). * * Counterpart to Solidity's `uint184` operator. * * Requirements: * * - input must fit into 184 bits */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(value); } /** * @dev Returns the downcasted uint176 from uint256, reverting on * overflow (when the input is greater than largest uint176). * * Counterpart to Solidity's `uint176` operator. * * Requirements: * * - input must fit into 176 bits */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(value); } /** * @dev Returns the downcasted uint168 from uint256, reverting on * overflow (when the input is greater than largest uint168). * * Counterpart to Solidity's `uint168` operator. * * Requirements: * * - input must fit into 168 bits */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(value); } /** * @dev Returns the downcasted uint160 from uint256, reverting on * overflow (when the input is greater than largest uint160). * * Counterpart to Solidity's `uint160` operator. * * Requirements: * * - input must fit into 160 bits */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(value); } /** * @dev Returns the downcasted uint152 from uint256, reverting on * overflow (when the input is greater than largest uint152). * * Counterpart to Solidity's `uint152` operator. * * Requirements: * * - input must fit into 152 bits */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(value); } /** * @dev Returns the downcasted uint144 from uint256, reverting on * overflow (when the input is greater than largest uint144). * * Counterpart to Solidity's `uint144` operator. * * Requirements: * * - input must fit into 144 bits */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(value); } /** * @dev Returns the downcasted uint136 from uint256, reverting on * overflow (when the input is greater than largest uint136). * * Counterpart to Solidity's `uint136` operator. * * Requirements: * * - input must fit into 136 bits */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(value); } /** * @dev Returns the downcasted uint128 from uint256, reverting on * overflow (when the input is greater than largest uint128). * * Counterpart to Solidity's `uint128` operator. * * Requirements: * * - input must fit into 128 bits */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(value); } /** * @dev Returns the downcasted uint120 from uint256, reverting on * overflow (when the input is greater than largest uint120). * * Counterpart to Solidity's `uint120` operator. * * Requirements: * * - input must fit into 120 bits */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(value); } /** * @dev Returns the downcasted uint112 from uint256, reverting on * overflow (when the input is greater than largest uint112). * * Counterpart to Solidity's `uint112` operator. * * Requirements: * * - input must fit into 112 bits */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(value); } /** * @dev Returns the downcasted uint104 from uint256, reverting on * overflow (when the input is greater than largest uint104). * * Counterpart to Solidity's `uint104` operator. * * Requirements: * * - input must fit into 104 bits */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(value); } /** * @dev Returns the downcasted uint96 from uint256, reverting on * overflow (when the input is greater than largest uint96). * * Counterpart to Solidity's `uint96` operator. * * Requirements: * * - input must fit into 96 bits */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(value); } /** * @dev Returns the downcasted uint88 from uint256, reverting on * overflow (when the input is greater than largest uint88). * * Counterpart to Solidity's `uint88` operator. * * Requirements: * * - input must fit into 88 bits */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(value); } /** * @dev Returns the downcasted uint80 from uint256, reverting on * overflow (when the input is greater than largest uint80). * * Counterpart to Solidity's `uint80` operator. * * Requirements: * * - input must fit into 80 bits */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(value); } /** * @dev Returns the downcasted uint72 from uint256, reverting on * overflow (when the input is greater than largest uint72). * * Counterpart to Solidity's `uint72` operator. * * Requirements: * * - input must fit into 72 bits */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(value); } /** * @dev Returns the downcasted uint64 from uint256, reverting on * overflow (when the input is greater than largest uint64). * * Counterpart to Solidity's `uint64` operator. * * Requirements: * * - input must fit into 64 bits */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(value); } /** * @dev Returns the downcasted uint56 from uint256, reverting on * overflow (when the input is greater than largest uint56). * * Counterpart to Solidity's `uint56` operator. * * Requirements: * * - input must fit into 56 bits */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(value); } /** * @dev Returns the downcasted uint48 from uint256, reverting on * overflow (when the input is greater than largest uint48). * * Counterpart to Solidity's `uint48` operator. * * Requirements: * * - input must fit into 48 bits */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(value); } /** * @dev Returns the downcasted uint40 from uint256, reverting on * overflow (when the input is greater than largest uint40). * * Counterpart to Solidity's `uint40` operator. * * Requirements: * * - input must fit into 40 bits */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(value); } /** * @dev Returns the downcasted uint32 from uint256, reverting on * overflow (when the input is greater than largest uint32). * * Counterpart to Solidity's `uint32` operator. * * Requirements: * * - input must fit into 32 bits */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(value); } /** * @dev Returns the downcasted uint24 from uint256, reverting on * overflow (when the input is greater than largest uint24). * * Counterpart to Solidity's `uint24` operator. * * Requirements: * * - input must fit into 24 bits */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(value); } /** * @dev Returns the downcasted uint16 from uint256, reverting on * overflow (when the input is greater than largest uint16). * * Counterpart to Solidity's `uint16` operator. * * Requirements: * * - input must fit into 16 bits */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(value); } /** * @dev Returns the downcasted uint8 from uint256, reverting on * overflow (when the input is greater than largest uint8). * * Counterpart to Solidity's `uint8` operator. * * Requirements: * * - input must fit into 8 bits */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(value); } /** * @dev Returns the downcasted int248 from int256, reverting on * overflow (when the input is less than smallest int248 or * greater than largest int248). * * Counterpart to Solidity's `int248` operator. * * Requirements: * * - input must fit into 248 bits */ function toInt248(int256 value) internal pure returns (int248 downcasted) { downcasted = int248(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(248, value); } } /** * @dev Returns the downcasted int240 from int256, reverting on * overflow (when the input is less than smallest int240 or * greater than largest int240). * * Counterpart to Solidity's `int240` operator. * * Requirements: * * - input must fit into 240 bits */ function toInt240(int256 value) internal pure returns (int240 downcasted) { downcasted = int240(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(240, value); } } /** * @dev Returns the downcasted int232 from int256, reverting on * overflow (when the input is less than smallest int232 or * greater than largest int232). * * Counterpart to Solidity's `int232` operator. * * Requirements: * * - input must fit into 232 bits */ function toInt232(int256 value) internal pure returns (int232 downcasted) { downcasted = int232(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(232, value); } } /** * @dev Returns the downcasted int224 from int256, reverting on * overflow (when the input is less than smallest int224 or * greater than largest int224). * * Counterpart to Solidity's `int224` operator. * * Requirements: * * - input must fit into 224 bits */ function toInt224(int256 value) internal pure returns (int224 downcasted) { downcasted = int224(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(224, value); } } /** * @dev Returns the downcasted int216 from int256, reverting on * overflow (when the input is less than smallest int216 or * greater than largest int216). * * Counterpart to Solidity's `int216` operator. * * Requirements: * * - input must fit into 216 bits */ function toInt216(int256 value) internal pure returns (int216 downcasted) { downcasted = int216(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(216, value); } } /** * @dev Returns the downcasted int208 from int256, reverting on * overflow (when the input is less than smallest int208 or * greater than largest int208). * * Counterpart to Solidity's `int208` operator. * * Requirements: * * - input must fit into 208 bits */ function toInt208(int256 value) internal pure returns (int208 downcasted) { downcasted = int208(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(208, value); } } /** * @dev Returns the downcasted int200 from int256, reverting on * overflow (when the input is less than smallest int200 or * greater than largest int200). * * Counterpart to Solidity's `int200` operator. * * Requirements: * * - input must fit into 200 bits */ function toInt200(int256 value) internal pure returns (int200 downcasted) { downcasted = int200(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(200, value); } } /** * @dev Returns the downcasted int192 from int256, reverting on * overflow (when the input is less than smallest int192 or * greater than largest int192). * * Counterpart to Solidity's `int192` operator. * * Requirements: * * - input must fit into 192 bits */ function toInt192(int256 value) internal pure returns (int192 downcasted) { downcasted = int192(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(192, value); } } /** * @dev Returns the downcasted int184 from int256, reverting on * overflow (when the input is less than smallest int184 or * greater than largest int184). * * Counterpart to Solidity's `int184` operator. * * Requirements: * * - input must fit into 184 bits */ function toInt184(int256 value) internal pure returns (int184 downcasted) { downcasted = int184(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(184, value); } } /** * @dev Returns the downcasted int176 from int256, reverting on * overflow (when the input is less than smallest int176 or * greater than largest int176). * * Counterpart to Solidity's `int176` operator. * * Requirements: * * - input must fit into 176 bits */ function toInt176(int256 value) internal pure returns (int176 downcasted) { downcasted = int176(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(176, value); } } /** * @dev Returns the downcasted int168 from int256, reverting on * overflow (when the input is less than smallest int168 or * greater than largest int168). * * Counterpart to Solidity's `int168` operator. * * Requirements: * * - input must fit into 168 bits */ function toInt168(int256 value) internal pure returns (int168 downcasted) { downcasted = int168(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(168, value); } } /** * @dev Returns the downcasted int160 from int256, reverting on * overflow (when the input is less than smallest int160 or * greater than largest int160). * * Counterpart to Solidity's `int160` operator. * * Requirements: * * - input must fit into 160 bits */ function toInt160(int256 value) internal pure returns (int160 downcasted) { downcasted = int160(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(160, value); } } /** * @dev Returns the downcasted int152 from int256, reverting on * overflow (when the input is less than smallest int152 or * greater than largest int152). * * Counterpart to Solidity's `int152` operator. * * Requirements: * * - input must fit into 152 bits */ function toInt152(int256 value) internal pure returns (int152 downcasted) { downcasted = int152(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(152, value); } } /** * @dev Returns the downcasted int144 from int256, reverting on * overflow (when the input is less than smallest int144 or * greater than largest int144). * * Counterpart to Solidity's `int144` operator. * * Requirements: * * - input must fit into 144 bits */ function toInt144(int256 value) internal pure returns (int144 downcasted) { downcasted = int144(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(144, value); } } /** * @dev Returns the downcasted int136 from int256, reverting on * overflow (when the input is less than smallest int136 or * greater than largest int136). * * Counterpart to Solidity's `int136` operator. * * Requirements: * * - input must fit into 136 bits */ function toInt136(int256 value) internal pure returns (int136 downcasted) { downcasted = int136(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(136, value); } } /** * @dev Returns the downcasted int128 from int256, reverting on * overflow (when the input is less than smallest int128 or * greater than largest int128). * * Counterpart to Solidity's `int128` operator. * * Requirements: * * - input must fit into 128 bits */ function toInt128(int256 value) internal pure returns (int128 downcasted) { downcasted = int128(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(128, value); } } /** * @dev Returns the downcasted int120 from int256, reverting on * overflow (when the input is less than smallest int120 or * greater than largest int120). * * Counterpart to Solidity's `int120` operator. * * Requirements: * * - input must fit into 120 bits */ function toInt120(int256 value) internal pure returns (int120 downcasted) { downcasted = int120(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(120, value); } } /** * @dev Returns the downcasted int112 from int256, reverting on * overflow (when the input is less than smallest int112 or * greater than largest int112). * * Counterpart to Solidity's `int112` operator. * * Requirements: * * - input must fit into 112 bits */ function toInt112(int256 value) internal pure returns (int112 downcasted) { downcasted = int112(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(112, value); } } /** * @dev Returns the downcasted int104 from int256, reverting on * overflow (when the input is less than smallest int104 or * greater than largest int104). * * Counterpart to Solidity's `int104` operator. * * Requirements: * * - input must fit into 104 bits */ function toInt104(int256 value) internal pure returns (int104 downcasted) { downcasted = int104(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(104, value); } } /** * @dev Returns the downcasted int96 from int256, reverting on * overflow (when the input is less than smallest int96 or * greater than largest int96). * * Counterpart to Solidity's `int96` operator. * * Requirements: * * - input must fit into 96 bits */ function toInt96(int256 value) internal pure returns (int96 downcasted) { downcasted = int96(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(96, value); } } /** * @dev Returns the downcasted int88 from int256, reverting on * overflow (when the input is less than smallest int88 or * greater than largest int88). * * Counterpart to Solidity's `int88` operator. * * Requirements: * * - input must fit into 88 bits */ function toInt88(int256 value) internal pure returns (int88 downcasted) { downcasted = int88(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(88, value); } } /** * @dev Returns the downcasted int80 from int256, reverting on * overflow (when the input is less than smallest int80 or * greater than largest int80). * * Counterpart to Solidity's `int80` operator. * * Requirements: * * - input must fit into 80 bits */ function toInt80(int256 value) internal pure returns (int80 downcasted) { downcasted = int80(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(80, value); } } /** * @dev Returns the downcasted int72 from int256, reverting on * overflow (when the input is less than smallest int72 or * greater than largest int72). * * Counterpart to Solidity's `int72` operator. * * Requirements: * * - input must fit into 72 bits */ function toInt72(int256 value) internal pure returns (int72 downcasted) { downcasted = int72(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(72, value); } } /** * @dev Returns the downcasted int64 from int256, reverting on * overflow (when the input is less than smallest int64 or * greater than largest int64). * * Counterpart to Solidity's `int64` operator. * * Requirements: * * - input must fit into 64 bits */ function toInt64(int256 value) internal pure returns (int64 downcasted) { downcasted = int64(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(64, value); } } /** * @dev Returns the downcasted int56 from int256, reverting on * overflow (when the input is less than smallest int56 or * greater than largest int56). * * Counterpart to Solidity's `int56` operator. * * Requirements: * * - input must fit into 56 bits */ function toInt56(int256 value) internal pure returns (int56 downcasted) { downcasted = int56(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(56, value); } } /** * @dev Returns the downcasted int48 from int256, reverting on * overflow (when the input is less than smallest int48 or * greater than largest int48). * * Counterpart to Solidity's `int48` operator. * * Requirements: * * - input must fit into 48 bits */ function toInt48(int256 value) internal pure returns (int48 downcasted) { downcasted = int48(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(48, value); } } /** * @dev Returns the downcasted int40 from int256, reverting on * overflow (when the input is less than smallest int40 or * greater than largest int40). * * Counterpart to Solidity's `int40` operator. * * Requirements: * * - input must fit into 40 bits */ function toInt40(int256 value) internal pure returns (int40 downcasted) { downcasted = int40(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(40, value); } } /** * @dev Returns the downcasted int32 from int256, reverting on * overflow (when the input is less than smallest int32 or * greater than largest int32). * * Counterpart to Solidity's `int32` operator. * * Requirements: * * - input must fit into 32 bits */ function toInt32(int256 value) internal pure returns (int32 downcasted) { downcasted = int32(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(32, value); } } /** * @dev Returns the downcasted int24 from int256, reverting on * overflow (when the input is less than smallest int24 or * greater than largest int24). * * Counterpart to Solidity's `int24` operator. * * Requirements: * * - input must fit into 24 bits */ function toInt24(int256 value) internal pure returns (int24 downcasted) { downcasted = int24(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(24, value); } } /** * @dev Returns the downcasted int16 from int256, reverting on * overflow (when the input is less than smallest int16 or * greater than largest int16). * * Counterpart to Solidity's `int16` operator. * * Requirements: * * - input must fit into 16 bits */ function toInt16(int256 value) internal pure returns (int16 downcasted) { downcasted = int16(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(16, value); } } /** * @dev Returns the downcasted int8 from int256, reverting on * overflow (when the input is less than smallest int8 or * greater than largest int8). * * Counterpart to Solidity's `int8` operator. * * Requirements: * * - input must fit into 8 bits */ function toInt8(int256 value) internal pure returns (int8 downcasted) { downcasted = int8(value); if (downcasted != value) { revert SafeCastOverflowedIntDowncast(8, value); } } /** * @dev Converts an unsigned uint256 into a signed int256. * * Requirements: * * - input must be less than or equal to maxInt256. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.20; import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol"; import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol"; import {Initializable} from "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. */ abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable __self = address(this); /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev The call is from an unauthorized context. */ error UUPSUnauthorizedCallContext(); /** * @dev The storage `slot` is unsupported as a UUID. */ error UUPSUnsupportedProxiableUUID(bytes32 slot); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { _checkProxy(); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { _checkNotDelegated(); _; } function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /** * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data); } /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC1967-compliant implementation pointing to self. * See {_onlyProxy}. */ function _checkProxy() internal view virtual { if ( address(this) == __self || // Must be called through delegatecall ERC1967Utils.getImplementation() != __self // Must be called through an active proxy ) { revert UUPSUnauthorizedCallContext(); } } /** * @dev Reverts if the execution is performed via delegatecall. * See {notDelegated}. */ function _checkNotDelegated() internal view virtual { if (address(this) != __self) { // Must not be called through delegatecall revert UUPSUnauthorizedCallContext(); } } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. * * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value * is expected to be the implementation slot in ERC1967. * * Emits an {IERC1967-Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { revert UUPSUnsupportedProxiableUUID(slot); } ERC1967Utils.upgradeToAndCall(newImplementation, data); } catch { // The implementation is not UUPS revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Arithmetic library with operations for fixed-point numbers. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/FixedPointMathLib.sol) /// @author Inspired by USM (https://github.com/usmfum/USM/blob/master/contracts/WadMath.sol) library FixedPointMathLib { /*////////////////////////////////////////////////////////////// SIMPLIFIED FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ uint256 internal constant MAX_UINT256 = 2**256 - 1; uint256 internal constant WAD = 1e18; // The scalar of ETH and most ERC20s. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, y, WAD); // Equivalent to (x * y) / WAD rounded up. } function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, WAD, y); // Equivalent to (x * WAD) / y rounded down. } function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivUp(x, WAD, y); // Equivalent to (x * WAD) / y rounded up. } /*////////////////////////////////////////////////////////////// LOW LEVEL FIXED POINT OPERATIONS //////////////////////////////////////////////////////////////*/ function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // Divide x * y by the denominator. z := div(mul(x, y), denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Equivalent to require(denominator != 0 && (y == 0 || x <= type(uint256).max / y)) if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) { revert(0, 0) } // If x * y modulo the denominator is strictly greater than 0, // 1 is added to round up the division of x * y by the denominator. z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator)) } } function rpow( uint256 x, uint256 n, uint256 scalar ) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { switch x case 0 { switch n case 0 { // 0 ** 0 = 1 z := scalar } default { // 0 ** n = 0 z := 0 } } default { switch mod(n, 2) case 0 { // If n is even, store scalar in z for now. z := scalar } default { // If n is odd, store x in z for now. z := x } // Shifting right by 1 is like dividing by 2. let half := shr(1, scalar) for { // Shift n right by 1 before looping to halve it. n := shr(1, n) } n { // Shift n right by 1 each iteration to halve it. n := shr(1, n) } { // Revert immediately if x ** 2 would overflow. // Equivalent to iszero(eq(div(xx, x), x)) here. if shr(128, x) { revert(0, 0) } // Store x squared. let xx := mul(x, x) // Round to the nearest number. let xxRound := add(xx, half) // Revert if xx + half overflowed. if lt(xxRound, xx) { revert(0, 0) } // Set x to scaled xxRound. x := div(xxRound, scalar) // If n is even: if mod(n, 2) { // Compute z * x. let zx := mul(z, x) // If z * x overflowed: if iszero(eq(div(zx, x), z)) { // Revert if x is non-zero. if iszero(iszero(x)) { revert(0, 0) } } // Round to the nearest number. let zxRound := add(zx, half) // Revert if zx + half overflowed. if lt(zxRound, zx) { revert(0, 0) } // Return properly scaled zxRound. z := div(zxRound, scalar) } } } } } /*////////////////////////////////////////////////////////////// GENERAL NUMBER UTILITIES //////////////////////////////////////////////////////////////*/ function sqrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { let y := x // We start y at x, which will help us make our initial estimate. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // We check y >= 2^(k + 8) but shift right by k bits // each branch to ensure that if x >= 256, then y >= 256. if iszero(lt(y, 0x10000000000000000000000000000000000)) { y := shr(128, y) z := shl(64, z) } if iszero(lt(y, 0x1000000000000000000)) { y := shr(64, y) z := shl(32, z) } if iszero(lt(y, 0x10000000000)) { y := shr(32, y) z := shl(16, z) } if iszero(lt(y, 0x1000000)) { y := shr(16, y) z := shl(8, z) } // Goal was to get z*z*y within a small factor of x. More iterations could // get y in a tighter range. Currently, we will have y in [256, 256*2^16). // We ensured y >= 256 so that the relative difference between y and y+1 is small. // That's not possible if x < 256 but we can just verify those cases exhaustively. // Now, z*z*y <= x < z*z*(y+1), and y <= 2^(16+8), and either y >= 256, or x < 256. // Correctness can be checked exhaustively for x < 256, so we assume y >= 256. // Then z*sqrt(y) is within sqrt(257)/sqrt(256) of sqrt(x), or about 20bps. // For s in the range [1/256, 256], the estimate f(s) = (181/1024) * (s+1) is in the range // (1/2.84 * sqrt(s), 2.84 * sqrt(s)), with largest error when s = 1 and when s = 256 or 1/256. // Since y is in [256, 256*2^16), let a = y/65536, so that a is in [1/256, 256). Then we can estimate // sqrt(y) using sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2^18. // There is no overflow risk here since y < 2^136 after the first branch above. z := shr(18, mul(z, add(y, 65536))) // A mul() is saved from starting z at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If x+1 is a perfect square, the Babylonian method cycles between // floor(sqrt(x)) and ceil(sqrt(x)). This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this statement. z := sub(z, lt(div(x, z), z)) } } function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Mod x by y. Note this will return // 0 instead of reverting if y is zero. z := mod(x, y) } } function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) { /// @solidity memory-safe-assembly assembly { // Divide x by y. Note this will return // 0 instead of reverting if y is zero. r := div(x, y) } } function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // Add 1 to x * y if x % y > 0. Note this will // return 0 instead of reverting if y is zero. z := add(gt(mod(x, y), 0), div(x, y)) } } }
// SPDX-License-Identifier: BUSL-1.1 // Central Limit Order Book (CLOB) exchange // (c) Long Gamma Labs, 2023. pragma solidity ^0.8.26; contract Errors { error AddressIsZero(); error ArrayLengthMismatch(); error ChainIsUnstableForTrades(); error ClaimNotAllowed(); error CommissionParamTooHigh(); error Disabled(); error EmptyOrderError(); error ExcessiveSignificantFigures(); error Expired(); error Forbidden(); error FractionalNumbersNotAllowed(); error InsufficientTokenXBalance(); error InsufficientTokenYBalance(); error InvalidCommissionRate(); error InvalidFloatingPointRepresentation(); error InvalidMarketMaker(); error InvalidPriceRange(); error InvalidTransfer(); error MarketOnlyAndPostOnlyFlagsConflict(); error MaxCommissionFailure(); error NativeETHDisabled(); error NonceExhaustedFailure(); error NotImplementedYet(); error OnlyOwnerCanCancelOrders(); error PointerAlreadyFreed(); error PriceExceedsMaximumAllowedValue(); error TransferFailed(); error UnknownOrderId(); error UnknownTrader(); error WrongOwner(); error ZeroMaxDelayNotAllowed(); error ZeroRecoveryTimeNotAllowed(); error ZeroTokenTransferNotAllowed(); }
// SPDX-License-Identifier: BUSL-1.1 // Central Limit Order Book (CLOB) exchange // (c) Long Gamma Labs, 2023. pragma solidity ^0.8.26; import {Errors} from "./Errors.sol"; library FP24 { /// @dev Converts a uint72 number into a uint24 floating point representation. /// @param a The uint72 number to be converted. /// @return p The uint24 floating point representation of the input number. function packFP24(uint72 a) internal pure returns (uint24) { require(0 < a && a <= 999999000000000000000, Errors.InvalidPriceRange()); uint72 threshold_number = 999999; uint8 e = 0; while (a > threshold_number) { require(a % 10 == 0, Errors.ExcessiveSignificantFigures()); a /= 10; e++; } uint24 p = (uint24(e) << 20) | uint24(a); return p; } /// @dev Converts a uint24 floating point number into a uint72 number. /// @param p The uint24 floating point number to be converted. /// @return a The uint72 number representation of the input floating point number. function unPackFP24(uint24 p) internal pure returns (uint72) { uint72 e = uint72(p >> 20); uint72 a = uint72(p & 0xfffff); require(0 < a && a <= 999999, Errors.InvalidFloatingPointRepresentation()); a *= uint72(10 ** e); return a; } }
// SPDX-License-Identifier: BUSL-1.1 // Central Limit Order Book (CLOB) exchange // (c) Long Gamma Labs, 2023. pragma solidity ^0.8.26; interface IWatchDog { function touch() external; function isChainStable() external view returns (bool); }
// SPDX-License-Identifier: BUSL-1.1 // Central Limit Order Book (CLOB) exchange // (c) Long Gamma Labs, 2023. pragma solidity ^0.8.26; interface IOnchainCLOB { function getConfig() external view returns ( uint256 _scaling_factor_token_x, uint256 _scaling_factor_token_y, address _token_x, address _token_y, bool _supports_native_eth, bool _is_token_x_weth, address _ask_trie, address _bid_trie, uint64 _admin_commission_rate, uint64 _total_aggressive_commission_rate, uint64 _total_passive_commission_rate, uint64 _passive_order_payout_rate, bool _should_invoke_on_trade ); receive() external payable; function getTraderBalance(address address_) external view returns (uint128, uint128, bool); function changeMarketMaker( address _marketmaker, bool _should_invoke_on_trade, uint64 _admin_commission_rate ) external; function setClaimableStatus(bool status) external; function placeOrder( bool isAsk, uint128 quantity, uint72 price, uint128 max_commission, bool market_only, bool post_only, bool transfer_executed_tokens, uint256 expires ) external payable returns ( uint64 order_id, uint128 executed_shares, uint128 executed_value, uint128 aggressive_fee ); function placeOrder( bool isAsk, uint128 quantity, uint72 price, uint128 max_commission, uint128 amount_to_approve, bool market_only, bool post_only, bool transfer_executed_tokens, uint256 expires, uint8 v, bytes32 r, bytes32 s ) external payable returns ( uint64 order_id, uint128 executed_shares, uint128 executed_value, uint128 aggressive_fee ); function placeMarketOrderWithTargetValue( bool isAsk, uint128 target_token_y_value, uint72 price, uint128 max_commission, uint128 amount_to_approve, bool transfer_executed_tokens, uint256 expires, uint8 v, bytes32 r, bytes32 s ) external payable returns ( uint128 executed_shares, uint128 executed_value, uint128 aggressive_fee ); function placeMarketOrderWithTargetValue( bool isAsk, uint128 target_token_y_value, uint72 price, uint128 max_commission, bool transfer_executed_tokens, uint256 expires ) external payable returns ( uint128 executed_shares, uint128 executed_value, uint128 aggressive_fee ); function claimOrder( uint64 order_id, bool only_claim, bool transfer_tokens, uint256 expires ) external; function batchClaim( address[] memory addresses, uint64[] memory order_ids, bool only_claim, uint256 expires ) external; function changeOrder( uint64 old_order_id, uint128 new_quantity, uint72 new_price, uint128 max_commission, bool post_only, bool transfer_tokens, uint256 expires ) external returns (uint64); function batchChangeOrder( uint64[] memory order_ids, uint128[] memory quantities, uint72[] memory prices, uint128 max_commission_per_order, bool post_only, bool transfer_tokens, uint256 expires ) external returns (uint64[] memory new_order_ids); function depositTokens(uint128 token_x_amount, uint128 token_y_amount) external; function depositTokens( uint128 token_x_amount, uint128 token_y_amount, uint8 v_x, bytes32 r_x, bytes32 s_x, uint8 v_y, bytes32 r_y, bytes32 s_y, uint256 expires ) external; function withdrawTokens(bool withdraw_all, uint128 token_x_amount, uint128 token_y_amount) external; function getAccumulatedFees() external returns (uint256); function transferFees() external; }
// SPDX-License-Identifier: BUSL-1.1 // Central Limit Order Book (CLOB) exchange // (c) Long Gamma Labs, 2023. pragma solidity ^0.8.26; interface ITrie { function best_offer() external view returns (uint64); function rightmost_map() external view returns (uint64); function addOrder(uint64 trader_id, uint64 order_id, uint128 shares, uint128 value) external; function removeOrder(uint64 order_id, uint64 order_trader_id) external returns (uint128 total_shares, uint128 remain_shares); function claimExecuted(uint64 order_id, uint64 order_trader_id) external returns (uint128 executed_shares, uint128 remain_shares); function getOrderInfo(uint64 order_id) external view returns (uint128 total_shares, uint128 remain_shares); function executeRight(uint64 order_id, uint128 order_total_shares) external returns (uint128 executed_shares, uint128 executed_value); function previewExecuteRight(uint64 order_id, uint128 max_shares, uint128 max_value) external view returns (uint128 executed_shares, uint128 executed_value); function assembleOrderbookFromOrders(uint24 max_price_levels) external view returns (uint24[] memory array_price_ids, uint128[] memory array_shares); }
// SPDX-License-Identifier: BUSL-1.1 // Central Limit Order Book (CLOB) exchange // (c) Long Gamma Labs, 2023. pragma solidity ^0.8.26; interface ITrieFactory { function createTrie(address lob) external returns (address); }
// SPDX-License-Identifier: BUSL-1.1 // Central Limit Order Book (CLOB) exchange // (c) Long Gamma Labs, 2023. pragma solidity ^0.8.0; interface ITradeConsumer { function onTrade(bool isAsk) external; }
// SPDX-License-Identifier: BUSL-1.1 // Central Limit Order Book (CLOB) exchange // (c) Long Gamma Labs, 2023. pragma solidity ^0.8.26; interface IWETH { function deposit() external payable; function withdraw(uint wad) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol"; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable { /// @custom:storage-location erc7201:openzeppelin.storage.Ownable struct OwnableStorage { address _owner; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300; function _getOwnableStorage() private pure returns (OwnableStorage storage $) { assembly { $.slot := OwnableStorageLocation } } /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ function __Ownable_init(address initialOwner) internal onlyInitializing { __Ownable_init_unchained(initialOwner); } function __Ownable_init_unchained(address initialOwner) internal onlyInitializing { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { OwnableStorage storage $ = _getOwnableStorage(); return $._owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { OwnableStorage storage $ = _getOwnableStorage(); address oldOwner = $._owner; $._owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; import {Initializable} from "../proxy/utils/Initializable.sol"; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract ContextUpgradeable is Initializable { function __Context_init() internal onlyInitializing { } function __Context_init_unchained() internal onlyInitializing { } function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.20; import {IBeacon} from "../beacon/IBeacon.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This abstract contract provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots. */ library ERC1967Utils { // We re-declare ERC-1967 events here because they can't be used directly from IERC1967. // This will be fixed in Solidity 0.8.21. At that point we should remove these events. /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the EIP1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by EIP1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the EIP1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the EIP1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @dev Library for reading and writing primitive types to specific storage slots. * * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts. * This library helps with reading and writing to such slots without the need for inline assembly. * * The functions in this library return Slot structs that contain a `value` member that can be used to read or write. * * Example usage to set ERC1967 implementation slot: * ```solidity * contract ERC1967 { * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; * * function _getImplementation() internal view returns (address) { * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value; * } * * function _setImplementation(address newImplementation) internal { * require(newImplementation.code.length > 0); * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation; * } * } * ``` */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } /** * @dev Returns an `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { /// @solidity memory-safe-assembly assembly { r.slot := store.slot } } }
{ "remappings": [ "forge-std/=lib/forge-std/src/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@solmate/src/=lib/solmate/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solmate/=lib/solmate/src/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "evmVersion": "cancun", "viaIR": true, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_watch_dog","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"AddressIsZero","type":"error"},{"inputs":[],"name":"ArrayLengthMismatch","type":"error"},{"inputs":[],"name":"ChainIsUnstableForTrades","type":"error"},{"inputs":[],"name":"ClaimNotAllowed","type":"error"},{"inputs":[{"internalType":"address","name":"implementation","type":"address"}],"name":"ERC1967InvalidImplementation","type":"error"},{"inputs":[],"name":"ERC1967NonPayable","type":"error"},{"inputs":[],"name":"EnforcedPause","type":"error"},{"inputs":[],"name":"ExcessiveSignificantFigures","type":"error"},{"inputs":[],"name":"ExpectedPause","type":"error"},{"inputs":[],"name":"Expired","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"Forbidden","type":"error"},{"inputs":[],"name":"InsufficientTokenXBalance","type":"error"},{"inputs":[],"name":"InsufficientTokenYBalance","type":"error"},{"inputs":[],"name":"InvalidCommissionRate","type":"error"},{"inputs":[],"name":"InvalidFloatingPointRepresentation","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidMarketMaker","type":"error"},{"inputs":[],"name":"InvalidPriceRange","type":"error"},{"inputs":[],"name":"InvalidTransfer","type":"error"},{"inputs":[],"name":"MarketOnlyAndPostOnlyFlagsConflict","type":"error"},{"inputs":[],"name":"MaxCommissionFailure","type":"error"},{"inputs":[],"name":"NativeETHDisabled","type":"error"},{"inputs":[],"name":"NonceExhaustedFailure","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"OnlyOwnerCanCancelOrders","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"uint8","name":"bits","type":"uint8"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"SafeCastOverflowedUintDowncast","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"UUPSUnauthorizedCallContext","type":"error"},{"inputs":[{"internalType":"bytes32","name":"slot","type":"bytes32"}],"name":"UUPSUnsupportedProxiableUUID","type":"error"},{"inputs":[],"name":"ZeroTokenTransferNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"bool","name":"status","type":"bool"}],"name":"ClaimableStatusChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint128","name":"token_x","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"token_y","type":"uint128"}],"name":"Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"new_marketmaker","type":"address"},{"indexed":false,"internalType":"address","name":"old_marketmaker","type":"address"}],"name":"MarketMakerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"order_id","type":"uint64"},{"indexed":false,"internalType":"uint128","name":"order_shares_remaining","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"token_x_sent","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"token_y_sent","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"passive_payout","type":"uint128"},{"indexed":false,"internalType":"bool","name":"only_claim","type":"bool"}],"name":"OrderClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint64","name":"order_id","type":"uint64"},{"indexed":true,"internalType":"bool","name":"isAsk","type":"bool"},{"indexed":false,"internalType":"uint128","name":"quantity","type":"uint128"},{"indexed":false,"internalType":"uint72","name":"price","type":"uint72"},{"indexed":false,"internalType":"uint128","name":"passive_shares","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"passive_fee","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"aggressive_shares","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"aggressive_value","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"aggressive_fee","type":"uint128"},{"indexed":false,"internalType":"bool","name":"market_only","type":"bool"},{"indexed":false,"internalType":"bool","name":"post_only","type":"bool"}],"name":"OrderPlaced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"new_pauser","type":"address"},{"indexed":false,"internalType":"address","name":"old_pauser","type":"address"}],"name":"PauserChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint128","name":"token_x","type":"uint128"},{"indexed":false,"internalType":"uint128","name":"token_y","type":"uint128"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"UPGRADE_INTERFACE_VERSION","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64[]","name":"order_ids","type":"uint64[]"},{"internalType":"uint128[]","name":"quantities","type":"uint128[]"},{"internalType":"uint72[]","name":"prices","type":"uint72[]"},{"internalType":"uint128","name":"max_commission_per_order","type":"uint128"},{"internalType":"bool","name":"post_only","type":"bool"},{"internalType":"bool","name":"transfer_tokens","type":"bool"},{"internalType":"uint256","name":"expires","type":"uint256"}],"name":"batchChangeOrder","outputs":[{"internalType":"uint64[]","name":"new_order_ids","type":"uint64[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"addresses","type":"address[]"},{"internalType":"uint64[]","name":"order_ids","type":"uint64[]"},{"internalType":"bool","name":"only_claim","type":"bool"},{"internalType":"uint256","name":"expires","type":"uint256"}],"name":"batchClaim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_marketmaker","type":"address"},{"internalType":"bool","name":"_should_invoke_on_trade","type":"bool"},{"internalType":"uint64","name":"_admin_commission_rate","type":"uint64"}],"name":"changeMarketMaker","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"old_order_id","type":"uint64"},{"internalType":"uint128","name":"new_quantity","type":"uint128"},{"internalType":"uint72","name":"new_price","type":"uint72"},{"internalType":"uint128","name":"max_commission","type":"uint128"},{"internalType":"bool","name":"post_only","type":"bool"},{"internalType":"bool","name":"transfer_tokens","type":"bool"},{"internalType":"uint256","name":"expires","type":"uint256"}],"name":"changeOrder","outputs":[{"internalType":"uint64","name":"order_id","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pauser_","type":"address"}],"name":"changePauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"order_id","type":"uint64"},{"internalType":"bool","name":"only_claim","type":"bool"},{"internalType":"bool","name":"transfer_tokens","type":"bool"},{"internalType":"uint256","name":"expires","type":"uint256"}],"name":"claimOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"token_x_amount","type":"uint128"},{"internalType":"uint128","name":"token_y_amount","type":"uint128"}],"name":"depositTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"token_x_amount","type":"uint128"},{"internalType":"uint128","name":"token_y_amount","type":"uint128"},{"internalType":"uint8","name":"v_x","type":"uint8"},{"internalType":"bytes32","name":"r_x","type":"bytes32"},{"internalType":"bytes32","name":"s_x","type":"bytes32"},{"internalType":"uint8","name":"v_y","type":"uint8"},{"internalType":"bytes32","name":"r_y","type":"bytes32"},{"internalType":"bytes32","name":"s_y","type":"bytes32"},{"internalType":"uint256","name":"expires","type":"uint256"}],"name":"depositTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAccumulatedFees","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getConfig","outputs":[{"internalType":"uint256","name":"_scaling_factor_token_x","type":"uint256"},{"internalType":"uint256","name":"_scaling_factor_token_y","type":"uint256"},{"internalType":"address","name":"_token_x","type":"address"},{"internalType":"address","name":"_token_y","type":"address"},{"internalType":"bool","name":"_supports_native_eth","type":"bool"},{"internalType":"bool","name":"_is_token_x_weth","type":"bool"},{"internalType":"address","name":"_ask_trie","type":"address"},{"internalType":"address","name":"_bid_trie","type":"address"},{"internalType":"uint64","name":"_admin_commission_rate","type":"uint64"},{"internalType":"uint64","name":"_total_aggressive_commission_rate","type":"uint64"},{"internalType":"uint64","name":"_total_passive_commission_rate","type":"uint64"},{"internalType":"uint64","name":"_passive_order_payout_rate","type":"uint64"},{"internalType":"bool","name":"_should_invoke_on_trade","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"address_","type":"address"}],"name":"getTraderBalance","outputs":[{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"uint128","name":"","type":"uint128"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_trie_factory","type":"address"},{"internalType":"address","name":"_tokenXAddress","type":"address"},{"internalType":"address","name":"_tokenYAddress","type":"address"},{"internalType":"bool","name":"_supports_native_eth","type":"bool"},{"internalType":"bool","name":"_is_token_x_weth","type":"bool"},{"internalType":"uint256","name":"scaling_token_x","type":"uint256"},{"internalType":"uint256","name":"scaling_token_y","type":"uint256"},{"internalType":"address","name":"_administrator","type":"address"},{"internalType":"address","name":"_marketmaker","type":"address"},{"internalType":"address","name":"_pauser","type":"address"},{"internalType":"bool","name":"_should_invoke_on_trade","type":"bool"},{"internalType":"uint64","name":"_admin_commission_rate","type":"uint64"},{"internalType":"uint64","name":"_total_aggressive_commission_rate","type":"uint64"},{"internalType":"uint64","name":"_total_passive_commission_rate","type":"uint64"},{"internalType":"uint64","name":"_passive_order_payout_rate","type":"uint64"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"marketmaker_config","outputs":[{"internalType":"address","name":"marketmaker","type":"address"},{"internalType":"bool","name":"should_invoke_on_trade","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nonce","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauser","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bool","name":"isAsk","type":"bool"},{"internalType":"uint128","name":"target_token_y_value","type":"uint128"},{"internalType":"uint72","name":"price","type":"uint72"},{"internalType":"uint128","name":"max_commission","type":"uint128"},{"internalType":"uint128","name":"amount_to_approve","type":"uint128"},{"internalType":"bool","name":"transfer_executed_tokens","type":"bool"},{"internalType":"uint256","name":"expires","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"placeMarketOrderWithTargetValue","outputs":[{"internalType":"uint128","name":"executed_shares","type":"uint128"},{"internalType":"uint128","name":"executed_value","type":"uint128"},{"internalType":"uint128","name":"aggressive_fee","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"isAsk","type":"bool"},{"internalType":"uint128","name":"target_token_y_value","type":"uint128"},{"internalType":"uint72","name":"price","type":"uint72"},{"internalType":"uint128","name":"max_commission","type":"uint128"},{"internalType":"bool","name":"transfer_executed_tokens","type":"bool"},{"internalType":"uint256","name":"expires","type":"uint256"}],"name":"placeMarketOrderWithTargetValue","outputs":[{"internalType":"uint128","name":"executed_shares","type":"uint128"},{"internalType":"uint128","name":"executed_value","type":"uint128"},{"internalType":"uint128","name":"aggressive_fee","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"isAsk","type":"bool"},{"internalType":"uint128","name":"quantity","type":"uint128"},{"internalType":"uint72","name":"price","type":"uint72"},{"internalType":"uint128","name":"max_commission","type":"uint128"},{"internalType":"uint128","name":"amount_to_approve","type":"uint128"},{"internalType":"bool","name":"market_only","type":"bool"},{"internalType":"bool","name":"post_only","type":"bool"},{"internalType":"bool","name":"transfer_executed_tokens","type":"bool"},{"internalType":"uint256","name":"expires","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"placeOrder","outputs":[{"internalType":"uint64","name":"order_id","type":"uint64"},{"internalType":"uint128","name":"executed_shares","type":"uint128"},{"internalType":"uint128","name":"executed_value","type":"uint128"},{"internalType":"uint128","name":"aggressive_fee","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"isAsk","type":"bool"},{"internalType":"uint128","name":"quantity","type":"uint128"},{"internalType":"uint72","name":"price","type":"uint72"},{"internalType":"uint128","name":"max_commission","type":"uint128"},{"internalType":"bool","name":"market_only","type":"bool"},{"internalType":"bool","name":"post_only","type":"bool"},{"internalType":"bool","name":"transfer_executed_tokens","type":"bool"},{"internalType":"uint256","name":"expires","type":"uint256"}],"name":"placeOrder","outputs":[{"internalType":"uint64","name":"order_id","type":"uint64"},{"internalType":"uint128","name":"executed_shares","type":"uint128"},{"internalType":"uint128","name":"executed_value","type":"uint128"},{"internalType":"uint128","name":"aggressive_fee","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"status","type":"bool"}],"name":"setClaimableStatus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"transferFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bool","name":"withdraw_all","type":"bool"},{"internalType":"uint128","name":"token_x_amount","type":"uint128"},{"internalType":"uint128","name":"token_y_amount","type":"uint128"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60c03461012657601f615f3c38819003918201601f19168301916001600160401b0383118484101761012a5780849260209460405283398101031261012657516001600160a01b03811690819003610126573060805260a0525f516020615f1c5f395f51905f525460ff8160401c16610117576002600160401b03196001600160401b038216016100c1575b604051615ddd908161013f82396080518181816124570152612526015260a051818181613da80152818161526e01526159750152f35b6001600160401b0319166001600160401b039081175f516020615f1c5f395f51905f52556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d290602090a15f61008b565b63f92ee8a960e01b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6101e080604052600436101561009c575b50361561001b575f80fd5b60035460ff8160a01c169081610043575b501561003457005b631dd2188d60e31b5f5260045ffd5b905060ff8160a81c16908180610087575b8215610063575b50505f61002c565b15915081610074575b505f8061005b565b6001600160a01b0316331490505f61006c565b6002546001600160a01b031633149250610054565b5f905f3560e01c908163151465f614612e155750806317911a49146127bf5780632cd271e7146127965780633f4ba83a146127185780634587c05f146126b65780634f1ef286146124ab57806352d1902d146124455780635671e8c9146123a95780635c975abb1461237b5780635df45a371461233e578063715018a6146122c15780637527527e1461216a578063783678c314611bbe578063789f290414611b185780637980e2cb146119bc57806379ba50971461195f5780637a94a42d146118285780638456cb59146117745780638da5cb5b1461173f5780639fd0506d14611716578063a38b6421146115f0578063ad3cb1cc14611594578063ad73d32e14611288578063affed0e01461125e578063c2fbe7bc1461123a578063c3f909d414611170578063db45bbfd14610ee2578063e30c397814610ead578063e4e117c114610874578063ead9b57f146105d0578063f2ba9102146103c2578063f2fde38b1461033c5763f513ef4c036100105761010036600319011261033957610224612f74565b61022c612fa1565b610234612ff9565b61023c612fb7565b610244612f56565b9061024d612f65565b92610256612f83565b9460e435421161032a578661029c979861026e6137d6565b6040519061027b82612e46565b808252806020830152806040830152606082015261029761379e565b613f28565b9060015f516020615d285f395f51905f52556103266001600160401b03835116916001600160801b03602085015116936102eb6001600160801b03606081604085015116930151169286613f44565b6040519485948592936001600160801b0380929695816060956001600160401b03608089019a16885216602087015216604085015216910152565b0390f35b630407b05b60e31b8852600488fd5b80fd5b503461033957602036600319011261033957610356612ead565b61035e613840565b5f516020615d685f395f51905f5280546001600160a01b0319166001600160a01b039283169081179091555f516020615ca85f395f51905f52549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227008380a380f35b5034610339576060366003190112610339576103dc612f74565b6103e4612fa1565b6044356001600160801b03811681036105cc576103ff61379e565b6104076137d6565b9091838491338652600a6020526001600160801b03604087205460401c16338752600a6020526001600160801b03600160408920015416916105c1575b6001600160801b0386169081610573575b50506001600160801b0384169081610503575b5050916104b091835f516020615ce85f395f51905f52946104e5575b50806104c7575b50604080516001600160801b0395861681529490911660208501523393918291820190565b0390a260015f516020615d285f395f51905f525580f35b6003546104df919033906001600160a01b031661421b565b5f61048b565b6002546104fd919033906001600160a01b031661421b565b5f610484565b90809293508110610565579161055b5f516020615ce85f395f51905f5294926104b094338952600a6020526001600160801b038086600160408d2001930316166001600160801b0319825416179055600154906136e5565b9281929450610468565b6201f70160e21b8652600486fd5b908092935081106105b257906105a26001600160801b03876105aa94338b52600a6020520316604089206136a0565b8654906136e5565b905f80610455565b63d0dd2cf360e01b8752600487fd5b945092508284610444565b8380fd5b50346103395760e0366003190112610339576004356001600160401b03811161087057610601903690600401612ed9565b90602435916001600160401b038311610870573660238401121561087057826004013561062d81612e96565b9361063b6040519586612e75565b8185526024602086019260051b8201019036821161086c57602401915b81831061084c575050506044356001600160401b038111610848573660238201121561084857806004013561068c81612e96565b9161069a6040519384612e75565b8183526024602084019260051b8201019036821161084457602401915b818310610820575050506106c9612fb7565b6106d1612f56565b906106da612f65565b9560c43593844211610811576106ee6137d6565b8551825181149081610806575b50156107f75785519561072661071088612e96565b9761071e604051998a612e75565b808952612e96565b602088019890601f1901368a37805b82518110156107aa578061078e898d8a8a8a8a6001600160481b03610786896001600160801b0361077e8f9d6001600160401b0360019f826107769161302a565b51169761302a565b51169361302a565b5116916130bf565b6001600160401b036107a0838d61302a565b9116905201610735565b508789604051928392602084019060208552518091526040840192915b8181106107d5575050500390f35b82516001600160401b03168452859450602093840193909201916001016107c7565b63512509d360e11b8752600487fd5b90508151145f6106fb565b630407b05b60e31b8752600487fd5b82356001600160481b0381168103610840578152602092830192016106b7565b8680fd5b8580fd5b8280fd5b82356001600160801b038116810361084457815260209283019201610658565b8480fd5b5080fd5b50346103395760803660031901126103395761088e612ec3565b610896612f92565b9161089f612f47565b916064354211610e9e576108b161379e565b6108b96137d6565b6108c233613873565b93338352600a60205260ff600160408520015460801c168015610e96575b15610e87576001808316148062ffffff8460281c1690610e7a575b620fffff81169060141c600f1681151580610e6d575b15610e5e57604d8111610e4a576001600160481b0390600a0a1602926001600160481b038416938403610e365784959685835f14610d18578415610c89575060048054604080516347ca7d2960e11b81526001600160401b03868116948201949094529390921660248401529196909187916044918391906001600160a01b03165af18015610c7e5786958791610c49575b50949086935b6109bc866109b787866137fd565b61381d565b956109d06109c988614256565b87986137fd565b935b600654608081901c6001600160401b031696908b908815610b43575050506001600160801b0391610a0688610a0c936137fd565b9061381d565b1693805f19048511810215670de0b6b3a76400000215610b3f5780610a3f670de0b6b3a7640000610a45938802046141ea565b956136e5565b6001600160801b03851690670de0b6b3a7640000820291808304670de0b6b3a76400001490151715610b2b5760c0610adb946001600160801b0398979489610a9f610ae499965f516020615c885f395f51905f5296613673565b9c5b6001600160401b0360405194168452166020830152898b16604083015289851660608301528986166080830152151560a0820152a1613680565b94600b54613759565b600b5516158015610b23575b15610b1457610b0092933361428d565b60015f516020615d285f395f51905f525580f35b6396e6bb8760e01b8352600483fd5b506001610af0565b634e487b7160e01b8a52601160045260248afd5b8880fd5b92919a93909750610b5d610b578a846137fd565b8261381d565b926001600160801b03610b6f85614256565b1693670de0b6b3a7640000850291858304670de0b6b3a76400001486151715610c355792610bcc610adb9996936001600160801b03610bc5819f9e9b98956001600160401b03610ae49f9c9960401c169061381d565b1690613673565b9d15610bef575b5050509160c091895f516020615c885f395f51905f5294610aa1565b5f516020615c885f395f51905f529593975060c09492610c24610c1e610c198f95610c2a9561381d565b614256565b916141ea565b906137fd565b969294829450610bd3565b634e487b7160e01b8f52601160045260248ffd5b9050610c6e91955060403d604011610c77575b610c668183612e75565b81019061377a565b9490945f6109a3565b503d610c5c565b6040513d88823e3d90fd5b6004805460408051631f43d3d960e31b81526001600160401b0387811694820194909452949092166024850152919792959392909186916044918391906001600160a01b03165af18015610d0d5787948891610ce8575b5093916109a9565b9050610d0491945060403d604011610c7757610c668183612e75565b9390935f610ce0565b6040513d89823e3d90fd5b8415610db55750600554604080516347ca7d2960e11b81526001600160401b0360018617811660048301529390931660248401529196879160449183916001600160a01b03165af18015610c7e5786958791610d90575b50949086935b610d7f85846137fd565b95610d8a818761381d565b936109d2565b9050610dac91955060403d604011610c7757610c668183612e75565b9490945f610d6f565b60055460408051631f43d3d960e31b81526001600160401b036001871781166004830152949094166024850152919792959392869160449183916001600160a01b03165af18015610d0d5787948891610e11575b509391610d75565b9050610e2d91945060403d604011610c7757610c668183612e75565b9390935f610e09565b634e487b7160e01b85526011600452602485fd5b634e487b7160e01b86526011600452602486fd5b63a25f85b760e01b8652600486fd5b50620f423f821115610911565b62ffffff908103166108fb565b6326831c8760e21b8352600483fd5b5060016108e0565b630407b05b60e31b8252600482fd5b50346103395780600319360112610339575f516020615d685f395f51905f52546040516001600160a01b039091168152602090f35b50346103395761012036600319011261033957610efd612fcd565b610f05612fa1565b6044359060ff821682036105cc5760a4359160ff8316830361086c576101043592610f2e6137d6565b6001600160801b03851690868215159384611103575b506001600160801b038516958615159283611089575b505050905f516020615c685f395f51905f52946104b0949392610f7b61379e565b610f836137d6565b88928994611048575b50610ffe575b5080610fde575b5080610fc45750604080516001600160801b0395861681529490911660208501523393918291820190565b6003546104df9190309033906001600160a01b0316613977565b600254610ff89190309033906001600160a01b0316613977565b5f610f99565b611041919250338852600a602052600160408920016001600160801b036110288682845416613680565b166001600160801b0319825416179055600154906136e5565b905f610f92565b611082919350338a52600a60205261107a60408b206110748b6001600160801b03835460401c16613680565b906136a0565b8954906136e5565b915f610f8c565b60018060a01b0360035416916110a16001548a6136e5565b92803b1561086c576110d7938580946040519687958694859363d505accf60e01b855260e4359260c435923033600489016136f8565b03925af16110e6575b80610f5a565b816110f5919695949396612e75565b61084057909192865f6110e0565b60018060a01b03600254169061111a8354866136e5565b90823b156105cc57611152928492838b936040519687958694859363d505accf60e01b855260843592606435923033600489016136f8565b03925af115610f44578161116591612e75565b61084057865f610f44565b50346103395780600319360112610339576101a090546001546001600160401b0360018060a01b03600254168160035460018060a01b036004541660ff60055492600654958260075460a01c16986040519a8b5260208b015260408a015260018060a01b03811660608a0152818160a01c16151560808a015260a81c16151560a088015260c087015260018060a01b03811660e087015260a01c16610100850152818116610120850152818160401c1661014085015260801c166101608301521515610180820152f35b50346103395780600319360112610339576112536137d6565b61125b613fe5565b80f35b503461033957806003193601126103395760206001600160401b0360085460a01c16604051908152f35b5060c03660031901126103395761129d612f74565b6112a5612fa1565b6112ad612ff9565b6112b5612fb7565b906112be612f56565b9260a4354211611585576112d06137d6565b6112e2856112dd846140fc565b6141a5565b906001600160801b036001600160401b0361130760065482808260801c169116613739565b169187156114a4571690670de0b6b3a76400000390670de0b6b3a76400008211611490577812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218111670de0b6b3a7640000021582021561148c57606461137a604093670de0b6b3a76400006001600160401b039402046141ea565b600554845163e146af4760e01b81529590931660048601526001600160801b0360248601819052166044850152839182906001600160a01b03165afa908115610c7e579486916113fd9682989161146c575b50915b604051906113dc82612e46565b80825280602083015280604083015260608201526113f861379e565b613c2a565b9060015f516020615d285f395f51905f52556103266001600160801b03602084015116916114406001600160801b03606081604088015116960151169184613f44565b604051938493849160409194936001600160801b03809281606087019816865216602085015216910152565b611485915060403d604011610c7757610c668183612e75565b505f6113cc565b8780fd5b634e487b7160e01b88526011600452602488fd5b1690670de0b6b3a7640000019081670de0b6b3a764000011611490577812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218111670de0b6b3a7640000021582021561148c57606461150f604093670de0b6b3a76400006001600160401b039402046141ea565b9360018060a01b03600454166001600160801b038551968795869463e146af4760e01b86521660048501528160248501521660448301525afa908115610c7e579486916113fd96829891611565575b50916113cf565b61157e915060403d604011610c7757610c668183612e75565b505f61155e565b630407b05b60e31b8652600486fd5b5034610339578060031936011261033957604080516115b38282612e75565b6005815260208101640352e302e360dc1b81528251938492602084525180928160208601528585015e828201840152601f01601f19168101030190f35b50346103395760603660031901126103395761160a612ead565b90611613612f92565b604435926001600160401b0384168085036105cc5761163061379e565b5f516020615ca85f395f51905f52546001600160a01b0316330361170757670de0b6b3a764000090611660613fe5565b116116f8576005805467ffffffffffffffff60a01b191660a09590951b67ffffffffffffffff60a01b16949094179093556007549192610b00926001600160a01b0390811690821681036116b5575b50613acc565b604080516001600160a01b0384811682529290921660208301527fe6603343f7aaffa5196c214e2249898291a999fa77d7f5f2ec1457d518724be791a15f6116af565b63047f2a9760e51b8352600483fd5b631dd2188d60e31b8452600484fd5b50346103395780600319360112610339576008546040516001600160a01b039091168152602090f35b50346103395780600319360112610339575f516020615ca85f395f51905f52546040516001600160a01b039091168152602090f35b50346103395780600319360112610339575f516020615ca85f395f51905f52546001600160a01b031633148015611814575b15611805576117b36137d6565b600160ff195f516020615d085f395f51905f525416175f516020615d085f395f51905f52557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b631dd2188d60e31b8152600490fd5b506008546001600160a01b031633146117a6565b506101403660031901126103395761183e612f74565b611846612fa1565b61184e612ff9565b611856612fb7565b9061185f612fe3565b92611868612f65565b9360e43560c43560ff82168203610b3f57804211611950579088929161188c6137d6565b881561193f576002546001600160a01b03165b6001600160a01b03169289156119245784546118c3916001600160801b03166136e5565b925b803b1561086c576118fc938580946040519687958694859363d505accf60e01b8552610124359261010435923033600489016136f8565b03925af161190f575b50506112d06137d6565b8161191991612e75565b61084457855f611905565b600154611939916001600160801b03166136e5565b926118c5565b6003546001600160a01b031661189f565b630407b05b60e31b8952600489fd5b503461033957806003193601126103395761197861379e565b611980613fe5565b5f516020615d685f395f51905f5254336001600160a01b03909116036119a957610b003361390c565b63118cdaa760e01b815233600452602490fd5b50610180366003190112611ad9576119d2612f74565b906119db612fa1565b6119e3612ff9565b906119ec612fb7565b916119f5612fe3565b926119fe612f65565b91611a07612f83565b9360e435958615158703611ad95761010435976101243560ff81168103611ad957894211611b0957611a376137d6565b8a15611af8576002546001600160a01b03165b6001600160a01b0316928b15611add575f54611a6e916001600160801b03166136e5565b905b833b15611ad95761029c9a8c94611aad935f80946040519687958694859363d505accf60e01b8552610164359261014435923033600489016136f8565b03925af1611ac4575b506040519061027b82612e46565b611ad192505f9150612e75565b875f5f611ab6565b5f80fd5b600154611af2916001600160801b03166136e5565b90611a70565b6003546001600160a01b0316611a4a565b630407b05b60e31b5f5260045ffd5b34611ad9576020366003190112611ad9576001600160a01b03611b39612ead565b165f52600a602052606060405f20604051611b5381612e46565b815460016001600160801b036001600160401b0383169283855260401c169384602085015201549060ff856001600160801b03841694856040820152019260801c161515825215611bb5575b5115159060405192835260208301526040820152f35b60018152611b9f565b34611ad9576101e0366003190112611ad957611bd8612ead565b6024356001600160a01b0381168103611ad9576044356001600160a01b0381168103611ad957606435908115158203611ad957611c13612f56565b60e435939091906001600160a01b0385168503611ad957610104356001600160a01b0381168103611ad95761012435906001600160a01b0382168203611ad95761014435918215158303611ad95761016435946001600160401b0386168603611ad95761018435976001600160401b0389168903611ad9576101a435976001600160401b0389168903611ad9576101c4359b6001600160401b038d168d03611ad9575f516020615d485f395f51905f52549b8c6001600160401b0381168015918261215b575b506001149081612151575b159081612148575b506121395760018d6001600160401b031916175f516020615d485f395f51905f525560ff8d60401c161561210d575b611d23614c0b565b611d2b614c0b565b611d33614c0b565b6001600160a01b038116156120fa57611d4b9061390c565b611d53614c0b565b611d5b614c0b565b611d63614c0b565b60015f516020615d285f395f51905f5255611d7c614c0b565b611d84614c0b565b5f516020615d085f395f51905f52805460ff191690556001600160a01b03169687156120eb576001600160a01b038116156120eb576001600160a01b038416156120eb576008805467ffffffffffffffff60a01b1916647fffffffff60a01b1790556009805467ffffffffffffffff1916905560a4355f90815560c435600155600280546001600160a01b0319166001600160a01b039384161790556003805494151560a01b60ff60a01b166001600160b01b031990951695909216949094179290921790151560a81b60ff60a81b161790556040516330b9c35160e01b81523060048201529060209082906024908290895af19485156120c3575f9560209287916120ce575b5060018060a01b03166001600160601b0360a01b60045416176004556024604051809781936330b9c35160e01b83523060048401525af180156120c357611f0f945f91612094575b5060018060a01b03166001600160601b0360a01b600554161760055560018060a01b03166001600160601b0360a01b6008541617600855613acc565b670de0b6b3a76400006001600160401b038216111580612079575b8061205e575b80612043575b80612021575b156120125760ff946fffffffffffffffff000000000000000091600554906001600160401b0360a01b9060a01b16906001600160401b0360a01b1916176005556001600160401b03600654918160801b9060801b169416906001600160401b0360c01b16179160401b1617176006556001600b5560401c1615611fbb57005b68ff0000000000000000195f516020615d485f395f51905f5254165f516020615d485f395f51905f52557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b63047f2a9760e51b5f5260045ffd5b506001600160401b0385161580611f3c57506001600160401b03821615611f3c565b506702c68af0bb1400006001600160401b0386161115611f36565b506702c68af0bb1400006001600160401b0383161115611f30565b506702c68af0bb1400006001600160401b0384161115611f2a565b6120b6915060203d6020116120bc575b6120ae8183612e75565b8101906136c6565b8a611ed3565b503d6120a4565b6040513d5f823e3d90fd5b6120e59150833d85116120bc576120ae8183612e75565b8c611e8b565b63867915ab60e01b5f5260045ffd5b631e4fbdf760e01b5f525f60045260245ffd5b68ffffffffffffffffff198d1668010000000000000001175f516020615d485f395f51905f5255611d1b565b63f92ee8a960e01b5f5260045ffd5b9050158f611cec565b303b159150611ce4565b60401c60ff161591508e611cd9565b34611ad9576040366003190112611ad957612183612fcd565b5f516020615c685f395f51905f5261220161219c612fa1565b6121a461379e565b6121ac6137d6565b5f806001600160801b03861680612288575b506001600160801b03831680612257575b5080612237575b50806122175750604080516001600160801b0395861681529490911660208501523393918291820190565b0390a260015f516020615d285f395f51905f5255005b6003546122319190309033906001600160a01b0316613977565b8461048b565b6002546122519190309033906001600160a01b0316613977565b856121d6565b612281919250335f52600a602052600160405f20016001600160801b036110288682845416613680565b90866121cf565b6122bb9150335f52600a6020526122b360405f20611074896001600160801b03835460401c16613680565b5f54906136e5565b866121be565b34611ad9575f366003190112611ad9576122d9613840565b5f516020615d685f395f51905f5280546001600160a01b03199081169091555f516020615ca85f395f51905f52805491821690555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34611ad9575f366003190112611ad957600b545f19810190811161236757602090604051908152f35b634e487b7160e01b5f52601160045260245ffd5b34611ad9575f366003190112611ad957602060ff5f516020615d085f395f51905f5254166040519015158152f35b34611ad9576020366003190112611ad9576123c2612f74565b6123ca61379e565b6123d26137d6565b6123db33613873565b50335f52600a602052600160405f200190151590805460ff60801b8360801b169060ff60801b19161790556040519081527fef2c823b0511fc89fd3e836ef444a74fb1cc0c6eff36f283e7f349c59a15da9860203392a260015f516020615d285f395f51905f5255005b34611ad9575f366003190112611ad9577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316300361249c5760206040515f516020615cc85f395f51905f528152f35b63703e46dd60e11b5f5260045ffd5b6040366003190112611ad9576124bf612ead565b602435906001600160401b038211611ad95736602383011215611ad9578160040135906124eb8261300f565b916124f96040519384612e75565b80835260208301933660248383010111611ad957815f926024602093018737840101526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016308114908115612694575b5061249c5761255e613840565b6040516352d1902d60e01b81526001600160a01b0382169390602081600481885afa5f9181612660575b506125a05784634c9c8ce360e01b5f5260045260245ffd5b805f516020615cc85f395f51905f5286920361264e5750823b1561263c575f516020615cc85f395f51905f5280546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2825115612623575f8091612621945190845af461261b614c36565b91614ddc565b005b5050503461262d57005b63b398979f60e01b5f5260045ffd5b634c9c8ce360e01b5f5260045260245ffd5b632a87526960e21b5f5260045260245ffd5b9091506020813d60201161268c575b8161267c60209383612e75565b81010312611ad957519086612588565b3d915061266f565b5f516020615cc85f395f51905f52546001600160a01b03161415905084612551565b34611ad95760e0366003190112611ad95760206127076126d4612ec3565b6126dc612fa1565b6126e4612ff9565b6126ec612fb7565b6126f4612f56565b916126fd612f65565b9360c435956130bf565b6001600160401b0360405191168152f35b34611ad9575f366003190112611ad957612730613840565b5f516020615d085f395f51905f525460ff8116156127875760ff19165f516020615d085f395f51905f52557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b5f5260045ffd5b34611ad9576020366003190112611ad9576126216127b2612ead565b6127ba613840565b613052565b34611ad9576080366003190112611ad9576004356001600160401b038111611ad95736602382011215611ad95780600401356127fa81612e96565b916128086040519384612e75565b8183526024602084019260051b82010190368211611ad957602401915b818310612df557836024356001600160401b038111611ad95761284c903690600401612ed9565b90612855612f47565b916064354211611b095761286761379e565b61286f6137d6565b8151815103612de6578215155f5b8351811015612dd3576001600160a01b03612898828661302a565b5116906128a5818561302a565b51916001600160401b038316926128bb82613873565b93825f52600a60205260ff600160405f20015460801c168015612dca575b15612dbb576001808316149160281c62ffffff1682612dae575b620fffff81169060141c600f1681151580612da1575b15612d9257604d8111612367576001600160481b0390600a0a1602946001600160481b038616958603612367575f8315612c6f578a15612bf0575060048054604080516347ca7d2960e11b81526001600160401b038681169482019490945293909216602484015291939291849060449082905f906001600160a01b03165af180156120c3575f935f91612bcc575b5092915f915b6129ac886109b785876137fd565b976129c06129b98a614256565b859a6137fd565b945b600654608081901c6001600160401b031694905f8615612afc575050506001600160801b0391610a06866129f5936137fd565b1691805f19048311810215670de0b6b3a76400000215611ad95780612a28670de0b6b3a7640000612a2e938602046141ea565b936136e5565b916001600160801b03811694670de0b6b3a7640000860295808704670de0b6b3a76400001490151715612367575f516020615c885f395f51905f5260c0612ab7946001600160801b03612a85819a612ac099613673565b9a5b604051928352166020820152888d166040820152888416606082015288851660808201528d60a0820152a1613680565b93600b54613759565b600b5516158015612af3575b15612ae45760019384612ade9361428d565b0161287d565b6396e6bb8760e01b5f5260045ffd5b50813314612acc565b9395509691939097612b17612b1188876137fd565b8761381d565b946001600160801b03612b2987614256565b1690670de0b6b3a7640000820297828904670de0b6b3a7640000148315171561236757612b77612ac0996001600160801b03610bc5612ab79b829f6001600160401b039060401c169061381d565b9b15612b99575b5050505f516020615c885f395f51905f52918860c092612a87565b60c09396505f516020615c885f395f51905f529492610c24610c1e610c198e95612bc29561381d565b9592829450612b7e565b9050612be791935060403d8111610c7757610c668183612e75565b9290928b612998565b6004805460408051631f43d3d960e31b81526001600160401b0387811694820194909452949092166024850152919491839060449082905f906001600160a01b03165af180156120c3575f925f91612c4b575b50919261299e565b9050612c6691925060403d8111610c7757610c668183612e75565b9190918c612c43565b8a15612d115750600554604080516347ca7d2960e11b81526001600160401b0360018617811660048301529093166024840152919392919084906001600160a01b0316815f816044810103925af180156120c3575f935f91612ced575b5092915f915b612cdc83856137fd565b97612ce7818561381d565b946129c2565b9050612d0891935060403d8111610c7757610c668183612e75565b9290928b612ccc565b60055460408051631f43d3d960e31b81526001600160401b03600187178116600483015290941660248501529194919083906001600160a01b0316815f816044810103925af180156120c3575f925f91612d6e575b509192612cd2565b9050612d8991925060403d8111610c7757610c668183612e75565b9190918c612d66565b63a25f85b760e01b5f5260045ffd5b50620f423f821115612909565b62ffffff908103166128f3565b6326831c8760e21b5f5260045ffd5b508233146128d9565b60015f516020615d285f395f51905f5255005b63512509d360e11b5f5260045ffd5b82356001600160a01b0381168103611ad957815260209283019201612825565b34611ad9575f366003190112611ad9576007546001600160a01b038116825260a01c60ff1615156020820152604090f35b608081019081106001600160401b03821117612e6157604052565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b03821117612e6157604052565b6001600160401b038111612e615760051b60200190565b600435906001600160a01b0382168203611ad957565b600435906001600160401b0382168203611ad957565b9080601f83011215611ad957813590612ef182612e96565b92612eff6040519485612e75565b82845260208085019360051b820101918211611ad957602001915b818310612f275750505090565b82356001600160401b0381168103611ad957815260209283019201612f1a565b604435908115158203611ad957565b608435908115158203611ad957565b60a435908115158203611ad957565b600435908115158203611ad957565b60c435908115158203611ad957565b602435908115158203611ad957565b602435906001600160801b0382168203611ad957565b606435906001600160801b0382168203611ad957565b600435906001600160801b0382168203611ad957565b608435906001600160801b0382168203611ad957565b604435906001600160481b0382168203611ad957565b6001600160401b038111612e6157601f01601f191660200190565b805182101561303e5760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b6008546001600160a01b03828116929082168381146130b957604080516001600160a01b0393841681529190921660208201527f95bb211a5a393c4d30c3edc9a745825fba4e6ad3e3bb949e6bf8ccdfe431a8119190a16001600160a01b03191617600855565b50505050565b9594919390926130cd6137d6565b5f9660016001600160401b03821611613189575b6001600160801b0385166130fa575b5050505050505090565b60019192939495969750811614954211611b095761317d9461314d9461311e6137d6565b8760405161312b81612e46565b5f81525f60208201525f60408201525f606082015261314861379e565b613f0f565b9160015f516020615d285f395f51905f52556001600160801b0360206001600160401b0385511694015116613f44565b5f8080808080806130f0565b864211611b095761319861379e565b6131a06137d6565b5f6131aa33613873565b335f818152600a602052604090206001015460801c60ff16801561366a575b15612dbb576001808516148062ffffff8660281c169061365d575b620fffff81169060141c600f1681151580613650575b15612d9257604d8111612367576001600160481b0390600a0a1602926001600160481b038416938403612367575f82156135b057851561352f575060048054604080516347ca7d2960e11b81526001600160401b038a81169482019490945293909216602484015291959392918690604490829087906001600160a01b03165af1801561352457839584916134ff575b50949083915b61329e866109b785846137fd565b956132b26132ab88614256565b85986137fd565b915b600654608081901c6001600160401b031694908890861561341b575050506001600160801b0391610a06866132e8936137fd565b1691805f19048311810215670de0b6b3a764000002156108445780612a28670de0b6b3a764000061331b938602046141ea565b6001600160801b03831690670de0b6b3a7640000820291808304670de0b6b3a7640000149015171561340757926133b8925f516020615c885f395f51905f5260c08c6001600160801b036133746133af97829b9a613673565b9d5b6001600160401b0360405193168352166020820152888c166040820152888416606082015288851660808201528a60a0820152a1613680565b96600b54613759565b600b5516159081156133fd575b50156133ee5750906133d891863361428d565b60015f516020615d285f395f51905f52556130e1565b6396e6bb8760e01b8152600490fd5b905033145f6133c5565b634e487b7160e01b87526011600452602487fd5b92919a9390955061342f610b5788846137fd565b926001600160801b0361344185614256565b1693670de0b6b3a7640000850291858304670de0b6b3a764000014861517156134eb57938e936134966133af98946001600160801b03610bc5819e9d9a966001600160401b036133b89e9b60401c169061381d565b9e156134b8575b5050505f516020615c885f395f51905f52918860c092613376565b60c09396505f516020615c885f395f51905f529492610c24610c1e610c198e956134e19561381d565b959282945061349d565b634e487b7160e01b8c52601160045260248cfd5b905061351b91955060403d604011610c7757610c668183612e75565b9490945f61328a565b6040513d85823e3d90fd5b6004805460408051631f43d3d960e31b81526001600160401b038b8116948201949094529490921660248501529196949391839060449082905f906001600160a01b03165af180156120c3575f925f9161358b575b5091613290565b90506135a791925060403d604011610c7757610c668183612e75565b9190915f613584565b60055460408051631f43d3d960e31b81526001600160401b0360018b1781166004830152909416602485015291965091945f9493909290919086906001600160a01b03168187816044810103925af19485156120c3575f905f9661362c575b5085926136268161362089856137fd565b9861381d565b916132b4565b905061364891955060403d604011610c7757610c668183612e75565b94905f61360f565b50620f423f8211156131fa565b62ffffff908103166131e4565b508033146131c9565b9190820391821161236757565b906001600160801b03809116911601906001600160801b03821161236757565b90600160401b600160c01b0382549160401b1690600160401b600160c01b031916179055565b90816020910312611ad957516001600160a01b0381168103611ad95790565b8181029291811591840414171561236757565b9360c095919897969360ff9360e087019a60018060a01b0316875260018060a01b031660208701526040860152606085015216608083015260a08201520152565b906001600160401b03809116911601906001600160401b03821161236757565b9190820180921161236757565b51906001600160801b0382168203611ad957565b9190826040910312611ad95761379b602061379484613766565b9301613766565b90565b60025f516020615d285f395f51905f5254146137c75760025f516020615d285f395f51905f5255565b633ee5aeb560e01b5f5260045ffd5b60ff5f516020615d085f395f51905f5254166137ee57565b63d93c066560e01b5f5260045ffd5b906001600160801b03809116911603906001600160801b03821161236757565b906001600160801b03809116911602906001600160801b03821691820361236757565b5f516020615ca85f395f51905f52546001600160a01b0316330361386057565b63118cdaa760e01b5f523360045260245ffd5b6001600160a01b03165f818152600a60205260409020546001600160401b03169190821561389e5750565b9150600954916001600160401b0383166001600160401b0381146123675767ffffffffffffffff199384166001600160401b0360019283019081169182176009555f938452600a6020526040909320805490951617845592909201805460ff60801b1916600160801b179055565b5f516020615d685f395f51905f5280546001600160a01b03199081169091555f516020615ca85f395f51905f5280549182166001600160a01b0393841690811790915591167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b6040516370a0823160e01b815230600482015291926001600160a01b0382169190602084602481865afa9384156120c3575f94613a79575b50602494602093926139fe92604051926323b872dd60e01b8785015260018060a01b03168884015260018060a01b03166044830152876064830152606482526139f9608483612e75565b614d44565b6040516370a0823160e01b815230600482015293849182905afa80156120c3575f90613a45575b613a2f9250613673565b03613a3657565b632f35253160e01b5f5260045ffd5b506020823d602011613a71575b81613a5f60209383612e75565b81010312611ad957613a2f9151613a25565b3d9150613a52565b9093506020929192813d602011613aac575b81613a9860209383612e75565b81010312611ad957519290919060246139af565b3d9150613a8b565b90816020910312611ad957518015158103611ad95790565b81613b3a575b6001600160a01b031680156120eb5760405160408101928184106001600160401b03851117612e6157602093604052828252151592839101526001600160601b0360a01b60075416176007556007549060ff60a01b9060a01b169060ff60a01b191617600755565b6040516301ffc9a760e01b8152630920cbe360e31b60048201526020816024816001600160a01b0386165afa9081156120c3575f91613b88575b50613ad2576309bfcb9b60e31b5f5260045ffd5b613baa915060203d602011613bb0575b613ba28183612e75565b810190613ab4565b5f613b74565b503d613b98565b90816020910312611ad957516001600160401b0381168103611ad95790565b6001600160401b0390911681526001600160801b03909116602082015260400190565b6001600160401b039182168152911660208201526001600160801b0391821660408201529116606082015260800190565b9594929391928691906001600160801b03851680151580613efd575b15613eef5734158015613ec3575b15613eb457613c66836112dd896140fc565b5f9390849081808415613e3a5750506005546040805163a558898f60e01b81529a90928b926001600160a01b03169183915f918391613ca9919060048401613bd6565b03925af19586156120c3575f985f97613e13575b50868997985b6001600160801b03613cde613cd784614c8c565b8096613680565b9b169182613d93575b6001600160801b03613d146060968280948760208a0152169687604082015283821698899101525f613680565b9216911611613d84576001600160481b03613d829b604051965f885260208801521660408601525f60608601525f608086015260a085015260c084015260e083015260016101008301525f6101208301521515905f516020615d885f395f51905f526101403392a33361468c565b565b6352866ea560e11b5f5260045ffd5b60405163371da77d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156120c3575f91613df4575b50613ce75763ab655c5560e01b5f5260045ffd5b613e0d915060203d602011613bb057613ba28183612e75565b5f613de0565b909650613e3091985060403d604011610c7757610c668183612e75565b979097955f613cbd565b979650979150613e6f9860409160018060a01b0360045416905f8451809d8195829463a558898f60e01b845260048401613bd6565b03925af19485156120c3575f985f96613e8d575b5085899692613cc3565b909550613eaa91985060403d604011610c7757610c668183612e75565b979097945f613e83565b6328745eb160e01b5f5260045ffd5b5060035460ff8160a01c169081613edb575b50613c54565b60ff915060a81c161515831515145f613ed5565b62f8653360e71b5f5260045ffd5b506001600160481b0387161515613c46565b613f2196610120525f61014052614e3a565b6101405190565b9096613f3e976101005260c0525f60e052615544565b60e05190565b6001600160801b031615613fa75760075460ff8160a01c1680613fb4575b613f6a575050565b6001600160a01b031690813b15611ad9575f91602483926040519485938492630920cbe360e31b8452151560048401525af180156120c357613faa575b50565b5f613d8291612e75565b50336001600160a01b0382161415613f62565b8115613fd1570490565b634e487b7160e01b5f52601260045260245ffd5b600b545f19810181811161236757670de0b6b3a7640000900490670de0b6b3a7640000820290821591838104670de0b6b3a7640000148317156123675761402b91613673565b600b55613fa75761409061407e60018060a01b035f516020615ca85f395f51905f5254169261407261406b6001600160401b0360055460a01c1683614daf565b8092613673565b806140af575b506141ea565b6001600160801b0360015491166136e5565b80614099575050565b600354613d8292906001600160a01b031661421b565b6140b8906141ea565b60018060a01b03600754165f52600a6020526001600160801b036140e6600160405f20019282845416613680565b166001600160801b03198254161790555f614078565b906001600160481b0382168015159081614191575b5015614182575f915b6001600160481b03811690620f423f82111561416a57506001600160481b03600a82061661415b57600a60ff9104921660ff8114612367576001019161411a565b632f17742b60e21b5f5260045ffd5b62f00000915062ffffff90939293169160141b161790565b6323f5f0b960e11b5f5260045ffd5b683635c6204739d98000915011155f614111565b67fffffffffffffffe906001925f146141cd5760271b677fffff8000000000165b821b161890565b62ffffff67ffffff8000000000911662ffffff0360271b166141c6565b6001600160801b038111614204576001600160801b031690565b6306dfcc6560e41b5f52608060045260245260445ffd5b60405163a9059cbb60e01b60208201526001600160a01b039092166024830152604480830193909352918152613d82916139f9606483612e75565b6001600160401b0360065460401c169081156142875761379b916001600160801b036142829216614daf565b6141ea565b50505f90565b9091925f80945f945f916003549660ff8860a81c1697885f1461467d57506002546001600160a01b0316975b34614601575b50906001600160801b031680156145f157821561459e576001600160801b03916142ee6142f4925f54906136e5565b90613759565b945b16908115614596571561453557906142ee61431492600154906136e5565b915b60035460ff8160a01c1661447d575b50918183819461442b575b5061440b575b806143bf575b506143a1575b50504761434d575050565b47906001600160a01b0316803b15610848578290600460405180948193630d0e30db60e41b83525af1801561439657614384575050565b61438f828092612e75565b6103395750565b6040513d84823e3d90fd5b6003546143b89230916001600160a01b0316613977565b5f82614342565b600354908460ff8360a01c16806143fd575b156143e6576143e09250614c65565b5f61433c565b6143f8926001600160a01b031661421b565b6143e0565b5060ff8360a81c16156143d1565b600254614426908390309087906001600160a01b0316613977565b614336565b60035460ff8160a01c16908161446f575b50156144525761444c9086614c65565b5f614330565b60025461446a919087906001600160a01b031661421b565b61444c565b60ff915060a81c165f61443c565b5f9060a81c60ff16808061452c575b61451a575b1580614511575b614501575b8015614325579091506001600160a01b03851690813b15611ad9575f91602483926040519485938492632e1a7d4d60e01b845260048401525af180156120c3576144ea575b908591614325565b6144f8919295505f90612e75565b5f93905f6144e2565b5061450c4784613673565b61449d565b50478411614498565b90506145264783613673565b90614491565b5047831161448c565b5f516020615c685f395f51905f52604060018060a09795971b03871692835f52600a6020526001825f20016001600160801b036145758382845416613680565b166001600160801b03198254161790558151905f82526020820152a2614316565b505091614316565b946001600160801b0391955f516020615c685f395f51905f52604060018060a01b038a1692835f52600a6020526145e0825f2061107483898354871c16613680565b81519081525f6020820152a26142f6565b50936001600160801b03906142f6565b1561464657506001600160801b0361463d6146365f546146306146276142828334613fc7565b918583166136e5565b94613680565b9234613673565b915b91906142bf565b9092506001600160801b0361467761467060015461466a6146276142828334613fc7565b98613680565b9634613673565b9361463f565b6001600160a01b0316976142b9565b92919390945f955f905f925f925f966003549960ff8b60a81c169a8b5f14614bfc57506002546001600160a01b03169a5b34614b94575b506001600160801b0382166001600160801b0382168181115f14614aaa575050036001600160801b03168315614a5857906142ee614703925f54906136e5565b945b6001600160801b0382166001600160801b0382168181115f14614964575050036001600160801b0316901561490357906142ee61474592600154906136e5565b915b60035460ff8160a01c16614858575b5080614806575b50806147e6575b508061479a575b508061477c5750504761434d575050565b6003546147939230916001600160a01b0316613977565b5f80614342565b600354908360ff8360a01c16806147d8575b156147c1576147bb9250614c65565b5f61476b565b6147d3926001600160a01b031661421b565b6147bb565b5060ff8360a81c16156147ac565b6002546148009190309086906001600160a01b0316613977565b5f614764565b60035460ff8160a01c16908161484a575b501561482d576148279085614c65565b5f61475d565b600254614845919086906001600160a01b031661421b565b614827565b60ff915060a81c165f614817565b5f9060a81c60ff1680806148fa575b6148e8575b15806148df575b6148cf575b8015614756576001600160a01b03871690813b15611ad9575f91602483926040519485938492632e1a7d4d60e01b845260048401525af180156120c35715614756576148c79197505f90612e75565b5f955f614756565b506148da4784613673565b614878565b50478411614873565b90506148f44783613673565b9061486c565b50478311614867565b5f516020615c685f395f51905f52604060018060a09795971b03881692835f52600a6020526001825f20016001600160801b036149438382845416613680565b166001600160801b03198254161790558151905f82526020820152a2614747565b909192935095939510614979575b5050614747565b6001600160a01b0387165f818152600a602052604090206001015490926001600160801b0392900382169116818110614a00575060405f516020615ce85f395f51905f5291835f52600a6020526001825f20016001600160801b038083818454160316166001600160801b03198254161790558151905f82526020820152a25b5f80614972565b95506040614a2a5f516020615ce85f395f51905f52926001600160801b03896001549203166136e5565b96835f52600a6020526001825f20016001600160801b031981541690558151905f82526020820152a26149f9565b5f516020615c685f395f51905f52604060018060a09a959a1b038b1692835f52600a602052614a99825f20611074836001600160801b038354871c16613680565b81519081525f6020820152a2614705565b98939810614aba575b5050614705565b6001600160801b0391031660018060a01b03891690815f52600a6020526001600160801b0360405f205460401c16818110155f14614b3d575060405f516020615ce85f395f51905f5291835f52600a602052614b29825f206001600160801b0383818354871c160316906136a0565b81519081525f6020820152a25b5f80614ab3565b96506040614b665f516020615ce85f395f51905f52926001600160801b038a5f549203166136e5565b97835f52600a602052815f20600160401b600160c01b0319815416905581519081525f6020820152a2614b36565b90929015614bcd5750614bc56146365f54614630614bb56142828334613fc7565b916001600160801b0383166136e5565b915b5f6146c3565b919450614bf6614bef600154614be9614bb56142828334613fc7565b99613680565b9734613673565b94614bc7565b6001600160a01b03169a6146bd565b60ff5f516020615d485f395f51905f525460401c1615614c2757565b631afcd79f60e31b5f5260045ffd5b3d15614c60573d90614c478261300f565b91614c556040519384612e75565b82523d5f602084013e565b606090565b5f80809381935af1614c75614c36565b5015614c7d57565b6312171d8360e31b5f5260045ffd5b6001600160801b03168015614d3f576006546001600160401b038160801c16916001600160401b03614cc084828516613739565b168015614d3757614cd19082614daf565b91670de0b6b3a7640000830290838204670de0b6b3a76400001484151715612367576142ee836001600160401b03614d1c614d2795614d1661379b9a614d2f996136e5565b90613673565b9360401c16906136e5565b600b54613759565b600b556141ea565b505050505f90565b505f90565b5f80614d6c9260018060a01b03169360208151910182865af1614d65614c36565b9083614ddc565b8051908115159182614d94575b5050614d825750565b635274afe760e01b5f5260045260245ffd5b614da79250602080918301019101613ab4565b155f80614d79565b815f19048111820215670de0b6b3a76400000215611ad95702670de0b6b3a7640000808204910615150190565b90614e005750805115614df157805190602001fd5b630a12f52160e11b5f5260045ffd5b81511580614e31575b614e11575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b15614e09565b9491939492909280610140525f916001600160801b038616151580615532575b15613eef5734159687159788615506575b15613eb4578492614e7b836140fc565b98614e86888b6141a5565b94615377575b50505f6101808190526101a08190526101c0819052978893849384939188156151a0575b505f99614ebd85826137fd565b925f946001600160801b038516614fae575b506001600160801b0380614ee38a88613680565b9216911611614f9f576040519a6001600160401b03168b526001600160801b031660208b01526001600160481b031660408a01526001600160801b031660608901526001600160801b031660808801526001600160801b031660a08701526001600160801b031660c08601526001600160801b031660e0850152610100840152151561012083015215159033906101405f516020615d885f395f51905f5291a36101c0516101a0516101805161012051613d829491903361468c565b6352866ea560e11b8852600488fd5b9194509b9a50600854906001600160401b03808360a01c16928160a01b5f19850160a01b16908260a01b1916178060085560a01c161561519157677fffff8000000000908b156151865762ffffff0360271b1617925b600167fffffffffffffffe85821b16189a61501e33613873565b6150316001600160481b0385168661381d565b6101605261504161016051614256565b958c156150e557506004546001600160a01b0316803b156150e157615088918b918f83899160405196879586948593635919321160e11b8552610160519260048601613bf9565b03925af180156150d65785918b916150bd575b50506150a691613680565b9b5b6001600160401b038c1661014051525f614ecf565b819250906150ca91612e75565b610b3f5783895f61509b565b6040513d8c823e3d90fd5b8a80fd5b600554929e9d90926001600160a01b031691823b15611ad95761512892875f809460405196879586948593635919321160e11b8552610160519260048601613bf9565b03925af180156120c357615169575b5067fffffffffffffffe9060011b169a6151606151578661016051613680565b6101c051613680565b6101c0526150a8565b6151769199505f90612e75565b5f9767fffffffffffffffe615137565b60271b161792615004565b63888ea83960e01b5f5260045ffd5b93509450925097865f146152fc57506040876151de9260018060a01b0360055416905f845180968195829463a558898f60e01b845260048401613bd6565b03925af19788156120c3575f915f996152d9575b50889282996101a0525b61520584614c8c565b94615213866101c051613680565b6101c0526001600160801b03841680615259575b60206101405101526001600160801b03851660406101405101526001600160801b03861660606101405101525f614eb0565b60405163371da77d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156120c3575f916152ba575b506152275763ab655c5560e01b5f5260045ffd5b6152d3915060203d602011613bb057613ba28183612e75565b5f6152a6565b9098506152f5915060403d604011610c7757610c668183612e75565b975f6151f2565b9760408861532c9360018060a01b0360045416905f845180978195829463a558898f60e01b845260048401613bd6565b03925af19283156120c3575f925f94615350575b508383610180526101c0526151fc565b90935061536d91925060403d604011610c7757610c668183612e75565b919091925f615340565b5f881561549357600554604051632e28668360e01b815290602090829060049082906001600160a01b03165afa80156120c3576001600160401b03915f91615464575b50166001600160401b038716111561545c575b15614e8c57935097505091506001600160481b03925061544d575b6001600160801b03604051945f86521660208501521660408301525f60608301525f60808301525f60a08301525f60c08301525f60e08301525f61010083015260016101208301521515905f516020615d885f395f51905f526101403392a361014052565b6154573433614c65565b6153e8565b5060016153cd565b615486915060203d60201161548c575b61547e8183612e75565b810190613bb7565b5f6153ba565b503d615474565b60048054604051632e28668360e01b81529160209183919082906001600160a01b03165afa80156120c3576001600160401b03915f916154e7575b50166001600160401b038716116153cd575060016153cd565b615500915060203d60201161548c5761547e8183612e75565b5f6154ce565b5060035460ff8160a01c16908161551e575b50614e6b565b60ff915060a81c161515861515145f615518565b506001600160481b0381161515614e5a565b939291909594958460e052831584615c5f575b15615c50575f916001600160801b038216151580615c3e575b15613eef5734159182159283615c0f575b15613eb4578896615591836140fc565b9361559f61010051866141a5565b9a615a86575b50505f6101608190526101a081905260808190526101c081905298899586959189156158a8575b505f61018052876158a1576155e186846137fd565b945b5f60a0526001600160801b0386166156ca575b506001600160801b038061560c8d60a051613680565b92169116116156bb57506001600160801b0397989388809693946001600160481b038296839560206040519e8f926001600160401b0361018051168452169101521660408c01521660608a01528160a0511660808a01521660a08801521660c08601521660e084015215156101008301521515610120820152610100511515905f516020615d885f395f51905f526101403392a3613d826101c0516101a0516080516101605160c0513361468c565b6352866ea560e11b8152600490fd5b600854906001600160401b03808360a01c16928160a01b5f19850160a01b16908260a01b1916178060085560a01c161561519157677fffff800000000090610100515f146158975762ffffff0360271b16175b600167fffffffffffffffe82821b16186101805261573a33613873565b610120526157516001600160481b0386168761381d565b6101405261576161014051614256565b60a05261010051156157fd57506004546001600160a01b0316803b1561084857826040518092635919321160e11b82528183816157ad610140518d610180516101205160048601613bf9565b03925af18015613524579083916157e8575b50506157cd85608051613680565b6080525b6001600160401b03610180511660e051525f6155f6565b816157f291612e75565b61087057815f6157bf565b6005546001600160a01b0316803b15611ad9575f6040518092635919321160e11b825281838161583d8d6101405190610180516101205160048601613bf9565b03925af180156120c35761587a575b5067fffffffffffffffe9060011b166101805261587161515760a05161014051613680565b6101c0526157d1565b6158879193505f90612e75565b5f9167fffffffffffffffe61584c565b60271b161761571d565b5f946155e3565b955099509450610100515f14615a07576040816158e79560018060a01b0360055416905f845180998195829463a558898f60e01b845260048401613bd6565b03925af19485156120c3575f945f966159e0575b5085856080526101a0525b61590f86614c8c565b9961591d8b6101c051613680565b6101c0526001600160801b03861680615960575b602060e05101526001600160801b038716604060e05101526001600160801b038b16606060e05101525f6155cc565b60405163371da77d60e01b81526020816004817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa9081156120c3575f916159c1575b506159315763ab655c5560e01b5f5260045ffd5b6159da915060203d602011613bb057613ba28183612e75565b5f6159ad565b9095506159fd91945060403d604011610c7757610c668183612e75565b939093945f6158fb565b600480546040805163a558898f60e01b815296909287926001600160a01b03169183915f918391615a3b9189918401613bd6565b03925af19485156120c3575f945f96615a5f575b508585610160526101c052615906565b909550615a7c91945060403d604011610c7757610c668183612e75565b939093945f615a4f565b5f610100515f14615b9c57600554604051632e28668360e01b815290602090829060049082906001600160a01b03165afa80156120c3576001600160401b03915f91615b7d575b50166001600160401b038d161115615b75575b156155a557945097985095509250506001600160481b039250615b66575b6001600160801b03604051935f85521660208401521660408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201526001610120820152610100511515905f516020615d885f395f51905f526101403392a360e052565b615b703433614c65565b615afe565b506001615ae0565b615b96915060203d60201161548c5761547e8183612e75565b5f615acd565b60048054604051632e28668360e01b81529160209183919082906001600160a01b03165afa80156120c3576001600160401b03915f91615bf0575b50166001600160401b038d1611615ae057506001615ae0565b615c09915060203d60201161548c5761547e8183612e75565b5f615bd7565b5060035460ff8160a01c169081615c27575b50615581565b60ff915060a81c161515610100511515145f615c21565b506001600160481b0381161515615570565b639aa6df0360e01b5f5260045ffd5b50861561555756fe91a0eb2c39ca4d8b85d038e494302fb14bda4920d009c0aa44f26960104adb97921a8ce27b6521c36c2f7901104535739cfb9dc28cd1bca46f5fe5913f0d079d9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc46a85bb068360778f28161eb8ac970939d29cc684f100323a8e5f120adc45ff1cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c007cbbf9e533e963aebd385f66fc01e69558a4fe08eb6c6bc0127fa292b0442800a2646970667358221220d6c6dd7d00db3d8928d1597ced112522ac59ce7379c0dc88729955f7d184034c64736f6c634300081c0033f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00000000000000000000000000b9d597d00627a6e451ba8c08fe7277f08533cc53
Deployed Bytecode
0x6101e080604052600436101561009c575b50361561001b575f80fd5b60035460ff8160a01c169081610043575b501561003457005b631dd2188d60e31b5f5260045ffd5b905060ff8160a81c16908180610087575b8215610063575b50505f61002c565b15915081610074575b505f8061005b565b6001600160a01b0316331490505f61006c565b6002546001600160a01b031633149250610054565b5f905f3560e01c908163151465f614612e155750806317911a49146127bf5780632cd271e7146127965780633f4ba83a146127185780634587c05f146126b65780634f1ef286146124ab57806352d1902d146124455780635671e8c9146123a95780635c975abb1461237b5780635df45a371461233e578063715018a6146122c15780637527527e1461216a578063783678c314611bbe578063789f290414611b185780637980e2cb146119bc57806379ba50971461195f5780637a94a42d146118285780638456cb59146117745780638da5cb5b1461173f5780639fd0506d14611716578063a38b6421146115f0578063ad3cb1cc14611594578063ad73d32e14611288578063affed0e01461125e578063c2fbe7bc1461123a578063c3f909d414611170578063db45bbfd14610ee2578063e30c397814610ead578063e4e117c114610874578063ead9b57f146105d0578063f2ba9102146103c2578063f2fde38b1461033c5763f513ef4c036100105761010036600319011261033957610224612f74565b61022c612fa1565b610234612ff9565b61023c612fb7565b610244612f56565b9061024d612f65565b92610256612f83565b9460e435421161032a578661029c979861026e6137d6565b6040519061027b82612e46565b808252806020830152806040830152606082015261029761379e565b613f28565b9060015f516020615d285f395f51905f52556103266001600160401b03835116916001600160801b03602085015116936102eb6001600160801b03606081604085015116930151169286613f44565b6040519485948592936001600160801b0380929695816060956001600160401b03608089019a16885216602087015216604085015216910152565b0390f35b630407b05b60e31b8852600488fd5b80fd5b503461033957602036600319011261033957610356612ead565b61035e613840565b5f516020615d685f395f51905f5280546001600160a01b0319166001600160a01b039283169081179091555f516020615ca85f395f51905f52549091167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e227008380a380f35b5034610339576060366003190112610339576103dc612f74565b6103e4612fa1565b6044356001600160801b03811681036105cc576103ff61379e565b6104076137d6565b9091838491338652600a6020526001600160801b03604087205460401c16338752600a6020526001600160801b03600160408920015416916105c1575b6001600160801b0386169081610573575b50506001600160801b0384169081610503575b5050916104b091835f516020615ce85f395f51905f52946104e5575b50806104c7575b50604080516001600160801b0395861681529490911660208501523393918291820190565b0390a260015f516020615d285f395f51905f525580f35b6003546104df919033906001600160a01b031661421b565b5f61048b565b6002546104fd919033906001600160a01b031661421b565b5f610484565b90809293508110610565579161055b5f516020615ce85f395f51905f5294926104b094338952600a6020526001600160801b038086600160408d2001930316166001600160801b0319825416179055600154906136e5565b9281929450610468565b6201f70160e21b8652600486fd5b908092935081106105b257906105a26001600160801b03876105aa94338b52600a6020520316604089206136a0565b8654906136e5565b905f80610455565b63d0dd2cf360e01b8752600487fd5b945092508284610444565b8380fd5b50346103395760e0366003190112610339576004356001600160401b03811161087057610601903690600401612ed9565b90602435916001600160401b038311610870573660238401121561087057826004013561062d81612e96565b9361063b6040519586612e75565b8185526024602086019260051b8201019036821161086c57602401915b81831061084c575050506044356001600160401b038111610848573660238201121561084857806004013561068c81612e96565b9161069a6040519384612e75565b8183526024602084019260051b8201019036821161084457602401915b818310610820575050506106c9612fb7565b6106d1612f56565b906106da612f65565b9560c43593844211610811576106ee6137d6565b8551825181149081610806575b50156107f75785519561072661071088612e96565b9761071e604051998a612e75565b808952612e96565b602088019890601f1901368a37805b82518110156107aa578061078e898d8a8a8a8a6001600160481b03610786896001600160801b0361077e8f9d6001600160401b0360019f826107769161302a565b51169761302a565b51169361302a565b5116916130bf565b6001600160401b036107a0838d61302a565b9116905201610735565b508789604051928392602084019060208552518091526040840192915b8181106107d5575050500390f35b82516001600160401b03168452859450602093840193909201916001016107c7565b63512509d360e11b8752600487fd5b90508151145f6106fb565b630407b05b60e31b8752600487fd5b82356001600160481b0381168103610840578152602092830192016106b7565b8680fd5b8580fd5b8280fd5b82356001600160801b038116810361084457815260209283019201610658565b8480fd5b5080fd5b50346103395760803660031901126103395761088e612ec3565b610896612f92565b9161089f612f47565b916064354211610e9e576108b161379e565b6108b96137d6565b6108c233613873565b93338352600a60205260ff600160408520015460801c168015610e96575b15610e87576001808316148062ffffff8460281c1690610e7a575b620fffff81169060141c600f1681151580610e6d575b15610e5e57604d8111610e4a576001600160481b0390600a0a1602926001600160481b038416938403610e365784959685835f14610d18578415610c89575060048054604080516347ca7d2960e11b81526001600160401b03868116948201949094529390921660248401529196909187916044918391906001600160a01b03165af18015610c7e5786958791610c49575b50949086935b6109bc866109b787866137fd565b61381d565b956109d06109c988614256565b87986137fd565b935b600654608081901c6001600160401b031696908b908815610b43575050506001600160801b0391610a0688610a0c936137fd565b9061381d565b1693805f19048511810215670de0b6b3a76400000215610b3f5780610a3f670de0b6b3a7640000610a45938802046141ea565b956136e5565b6001600160801b03851690670de0b6b3a7640000820291808304670de0b6b3a76400001490151715610b2b5760c0610adb946001600160801b0398979489610a9f610ae499965f516020615c885f395f51905f5296613673565b9c5b6001600160401b0360405194168452166020830152898b16604083015289851660608301528986166080830152151560a0820152a1613680565b94600b54613759565b600b5516158015610b23575b15610b1457610b0092933361428d565b60015f516020615d285f395f51905f525580f35b6396e6bb8760e01b8352600483fd5b506001610af0565b634e487b7160e01b8a52601160045260248afd5b8880fd5b92919a93909750610b5d610b578a846137fd565b8261381d565b926001600160801b03610b6f85614256565b1693670de0b6b3a7640000850291858304670de0b6b3a76400001486151715610c355792610bcc610adb9996936001600160801b03610bc5819f9e9b98956001600160401b03610ae49f9c9960401c169061381d565b1690613673565b9d15610bef575b5050509160c091895f516020615c885f395f51905f5294610aa1565b5f516020615c885f395f51905f529593975060c09492610c24610c1e610c198f95610c2a9561381d565b614256565b916141ea565b906137fd565b969294829450610bd3565b634e487b7160e01b8f52601160045260248ffd5b9050610c6e91955060403d604011610c77575b610c668183612e75565b81019061377a565b9490945f6109a3565b503d610c5c565b6040513d88823e3d90fd5b6004805460408051631f43d3d960e31b81526001600160401b0387811694820194909452949092166024850152919792959392909186916044918391906001600160a01b03165af18015610d0d5787948891610ce8575b5093916109a9565b9050610d0491945060403d604011610c7757610c668183612e75565b9390935f610ce0565b6040513d89823e3d90fd5b8415610db55750600554604080516347ca7d2960e11b81526001600160401b0360018617811660048301529390931660248401529196879160449183916001600160a01b03165af18015610c7e5786958791610d90575b50949086935b610d7f85846137fd565b95610d8a818761381d565b936109d2565b9050610dac91955060403d604011610c7757610c668183612e75565b9490945f610d6f565b60055460408051631f43d3d960e31b81526001600160401b036001871781166004830152949094166024850152919792959392869160449183916001600160a01b03165af18015610d0d5787948891610e11575b509391610d75565b9050610e2d91945060403d604011610c7757610c668183612e75565b9390935f610e09565b634e487b7160e01b85526011600452602485fd5b634e487b7160e01b86526011600452602486fd5b63a25f85b760e01b8652600486fd5b50620f423f821115610911565b62ffffff908103166108fb565b6326831c8760e21b8352600483fd5b5060016108e0565b630407b05b60e31b8252600482fd5b50346103395780600319360112610339575f516020615d685f395f51905f52546040516001600160a01b039091168152602090f35b50346103395761012036600319011261033957610efd612fcd565b610f05612fa1565b6044359060ff821682036105cc5760a4359160ff8316830361086c576101043592610f2e6137d6565b6001600160801b03851690868215159384611103575b506001600160801b038516958615159283611089575b505050905f516020615c685f395f51905f52946104b0949392610f7b61379e565b610f836137d6565b88928994611048575b50610ffe575b5080610fde575b5080610fc45750604080516001600160801b0395861681529490911660208501523393918291820190565b6003546104df9190309033906001600160a01b0316613977565b600254610ff89190309033906001600160a01b0316613977565b5f610f99565b611041919250338852600a602052600160408920016001600160801b036110288682845416613680565b166001600160801b0319825416179055600154906136e5565b905f610f92565b611082919350338a52600a60205261107a60408b206110748b6001600160801b03835460401c16613680565b906136a0565b8954906136e5565b915f610f8c565b60018060a01b0360035416916110a16001548a6136e5565b92803b1561086c576110d7938580946040519687958694859363d505accf60e01b855260e4359260c435923033600489016136f8565b03925af16110e6575b80610f5a565b816110f5919695949396612e75565b61084057909192865f6110e0565b60018060a01b03600254169061111a8354866136e5565b90823b156105cc57611152928492838b936040519687958694859363d505accf60e01b855260843592606435923033600489016136f8565b03925af115610f44578161116591612e75565b61084057865f610f44565b50346103395780600319360112610339576101a090546001546001600160401b0360018060a01b03600254168160035460018060a01b036004541660ff60055492600654958260075460a01c16986040519a8b5260208b015260408a015260018060a01b03811660608a0152818160a01c16151560808a015260a81c16151560a088015260c087015260018060a01b03811660e087015260a01c16610100850152818116610120850152818160401c1661014085015260801c166101608301521515610180820152f35b50346103395780600319360112610339576112536137d6565b61125b613fe5565b80f35b503461033957806003193601126103395760206001600160401b0360085460a01c16604051908152f35b5060c03660031901126103395761129d612f74565b6112a5612fa1565b6112ad612ff9565b6112b5612fb7565b906112be612f56565b9260a4354211611585576112d06137d6565b6112e2856112dd846140fc565b6141a5565b906001600160801b036001600160401b0361130760065482808260801c169116613739565b169187156114a4571690670de0b6b3a76400000390670de0b6b3a76400008211611490577812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218111670de0b6b3a7640000021582021561148c57606461137a604093670de0b6b3a76400006001600160401b039402046141ea565b600554845163e146af4760e01b81529590931660048601526001600160801b0360248601819052166044850152839182906001600160a01b03165afa908115610c7e579486916113fd9682989161146c575b50915b604051906113dc82612e46565b80825280602083015280604083015260608201526113f861379e565b613c2a565b9060015f516020615d285f395f51905f52556103266001600160801b03602084015116916114406001600160801b03606081604088015116960151169184613f44565b604051938493849160409194936001600160801b03809281606087019816865216602085015216910152565b611485915060403d604011610c7757610c668183612e75565b505f6113cc565b8780fd5b634e487b7160e01b88526011600452602488fd5b1690670de0b6b3a7640000019081670de0b6b3a764000011611490577812725dd1d243aba0e75fe645cc4873f9e65afe688c928e1f218111670de0b6b3a7640000021582021561148c57606461150f604093670de0b6b3a76400006001600160401b039402046141ea565b9360018060a01b03600454166001600160801b038551968795869463e146af4760e01b86521660048501528160248501521660448301525afa908115610c7e579486916113fd96829891611565575b50916113cf565b61157e915060403d604011610c7757610c668183612e75565b505f61155e565b630407b05b60e31b8652600486fd5b5034610339578060031936011261033957604080516115b38282612e75565b6005815260208101640352e302e360dc1b81528251938492602084525180928160208601528585015e828201840152601f01601f19168101030190f35b50346103395760603660031901126103395761160a612ead565b90611613612f92565b604435926001600160401b0384168085036105cc5761163061379e565b5f516020615ca85f395f51905f52546001600160a01b0316330361170757670de0b6b3a764000090611660613fe5565b116116f8576005805467ffffffffffffffff60a01b191660a09590951b67ffffffffffffffff60a01b16949094179093556007549192610b00926001600160a01b0390811690821681036116b5575b50613acc565b604080516001600160a01b0384811682529290921660208301527fe6603343f7aaffa5196c214e2249898291a999fa77d7f5f2ec1457d518724be791a15f6116af565b63047f2a9760e51b8352600483fd5b631dd2188d60e31b8452600484fd5b50346103395780600319360112610339576008546040516001600160a01b039091168152602090f35b50346103395780600319360112610339575f516020615ca85f395f51905f52546040516001600160a01b039091168152602090f35b50346103395780600319360112610339575f516020615ca85f395f51905f52546001600160a01b031633148015611814575b15611805576117b36137d6565b600160ff195f516020615d085f395f51905f525416175f516020615d085f395f51905f52557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a180f35b631dd2188d60e31b8152600490fd5b506008546001600160a01b031633146117a6565b506101403660031901126103395761183e612f74565b611846612fa1565b61184e612ff9565b611856612fb7565b9061185f612fe3565b92611868612f65565b9360e43560c43560ff82168203610b3f57804211611950579088929161188c6137d6565b881561193f576002546001600160a01b03165b6001600160a01b03169289156119245784546118c3916001600160801b03166136e5565b925b803b1561086c576118fc938580946040519687958694859363d505accf60e01b8552610124359261010435923033600489016136f8565b03925af161190f575b50506112d06137d6565b8161191991612e75565b61084457855f611905565b600154611939916001600160801b03166136e5565b926118c5565b6003546001600160a01b031661189f565b630407b05b60e31b8952600489fd5b503461033957806003193601126103395761197861379e565b611980613fe5565b5f516020615d685f395f51905f5254336001600160a01b03909116036119a957610b003361390c565b63118cdaa760e01b815233600452602490fd5b50610180366003190112611ad9576119d2612f74565b906119db612fa1565b6119e3612ff9565b906119ec612fb7565b916119f5612fe3565b926119fe612f65565b91611a07612f83565b9360e435958615158703611ad95761010435976101243560ff81168103611ad957894211611b0957611a376137d6565b8a15611af8576002546001600160a01b03165b6001600160a01b0316928b15611add575f54611a6e916001600160801b03166136e5565b905b833b15611ad95761029c9a8c94611aad935f80946040519687958694859363d505accf60e01b8552610164359261014435923033600489016136f8565b03925af1611ac4575b506040519061027b82612e46565b611ad192505f9150612e75565b875f5f611ab6565b5f80fd5b600154611af2916001600160801b03166136e5565b90611a70565b6003546001600160a01b0316611a4a565b630407b05b60e31b5f5260045ffd5b34611ad9576020366003190112611ad9576001600160a01b03611b39612ead565b165f52600a602052606060405f20604051611b5381612e46565b815460016001600160801b036001600160401b0383169283855260401c169384602085015201549060ff856001600160801b03841694856040820152019260801c161515825215611bb5575b5115159060405192835260208301526040820152f35b60018152611b9f565b34611ad9576101e0366003190112611ad957611bd8612ead565b6024356001600160a01b0381168103611ad9576044356001600160a01b0381168103611ad957606435908115158203611ad957611c13612f56565b60e435939091906001600160a01b0385168503611ad957610104356001600160a01b0381168103611ad95761012435906001600160a01b0382168203611ad95761014435918215158303611ad95761016435946001600160401b0386168603611ad95761018435976001600160401b0389168903611ad9576101a435976001600160401b0389168903611ad9576101c4359b6001600160401b038d168d03611ad9575f516020615d485f395f51905f52549b8c6001600160401b0381168015918261215b575b506001149081612151575b159081612148575b506121395760018d6001600160401b031916175f516020615d485f395f51905f525560ff8d60401c161561210d575b611d23614c0b565b611d2b614c0b565b611d33614c0b565b6001600160a01b038116156120fa57611d4b9061390c565b611d53614c0b565b611d5b614c0b565b611d63614c0b565b60015f516020615d285f395f51905f5255611d7c614c0b565b611d84614c0b565b5f516020615d085f395f51905f52805460ff191690556001600160a01b03169687156120eb576001600160a01b038116156120eb576001600160a01b038416156120eb576008805467ffffffffffffffff60a01b1916647fffffffff60a01b1790556009805467ffffffffffffffff1916905560a4355f90815560c435600155600280546001600160a01b0319166001600160a01b039384161790556003805494151560a01b60ff60a01b166001600160b01b031990951695909216949094179290921790151560a81b60ff60a81b161790556040516330b9c35160e01b81523060048201529060209082906024908290895af19485156120c3575f9560209287916120ce575b5060018060a01b03166001600160601b0360a01b60045416176004556024604051809781936330b9c35160e01b83523060048401525af180156120c357611f0f945f91612094575b5060018060a01b03166001600160601b0360a01b600554161760055560018060a01b03166001600160601b0360a01b6008541617600855613acc565b670de0b6b3a76400006001600160401b038216111580612079575b8061205e575b80612043575b80612021575b156120125760ff946fffffffffffffffff000000000000000091600554906001600160401b0360a01b9060a01b16906001600160401b0360a01b1916176005556001600160401b03600654918160801b9060801b169416906001600160401b0360c01b16179160401b1617176006556001600b5560401c1615611fbb57005b68ff0000000000000000195f516020615d485f395f51905f5254165f516020615d485f395f51905f52557fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2602060405160018152a1005b63047f2a9760e51b5f5260045ffd5b506001600160401b0385161580611f3c57506001600160401b03821615611f3c565b506702c68af0bb1400006001600160401b0386161115611f36565b506702c68af0bb1400006001600160401b0383161115611f30565b506702c68af0bb1400006001600160401b0384161115611f2a565b6120b6915060203d6020116120bc575b6120ae8183612e75565b8101906136c6565b8a611ed3565b503d6120a4565b6040513d5f823e3d90fd5b6120e59150833d85116120bc576120ae8183612e75565b8c611e8b565b63867915ab60e01b5f5260045ffd5b631e4fbdf760e01b5f525f60045260245ffd5b68ffffffffffffffffff198d1668010000000000000001175f516020615d485f395f51905f5255611d1b565b63f92ee8a960e01b5f5260045ffd5b9050158f611cec565b303b159150611ce4565b60401c60ff161591508e611cd9565b34611ad9576040366003190112611ad957612183612fcd565b5f516020615c685f395f51905f5261220161219c612fa1565b6121a461379e565b6121ac6137d6565b5f806001600160801b03861680612288575b506001600160801b03831680612257575b5080612237575b50806122175750604080516001600160801b0395861681529490911660208501523393918291820190565b0390a260015f516020615d285f395f51905f5255005b6003546122319190309033906001600160a01b0316613977565b8461048b565b6002546122519190309033906001600160a01b0316613977565b856121d6565b612281919250335f52600a602052600160405f20016001600160801b036110288682845416613680565b90866121cf565b6122bb9150335f52600a6020526122b360405f20611074896001600160801b03835460401c16613680565b5f54906136e5565b866121be565b34611ad9575f366003190112611ad9576122d9613840565b5f516020615d685f395f51905f5280546001600160a01b03199081169091555f516020615ca85f395f51905f52805491821690555f906001600160a01b03167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b34611ad9575f366003190112611ad957600b545f19810190811161236757602090604051908152f35b634e487b7160e01b5f52601160045260245ffd5b34611ad9575f366003190112611ad957602060ff5f516020615d085f395f51905f5254166040519015158152f35b34611ad9576020366003190112611ad9576123c2612f74565b6123ca61379e565b6123d26137d6565b6123db33613873565b50335f52600a602052600160405f200190151590805460ff60801b8360801b169060ff60801b19161790556040519081527fef2c823b0511fc89fd3e836ef444a74fb1cc0c6eff36f283e7f349c59a15da9860203392a260015f516020615d285f395f51905f5255005b34611ad9575f366003190112611ad9577f000000000000000000000000c4a24a83c92fa5ecc5207c71ac62dcd26709ad8e6001600160a01b0316300361249c5760206040515f516020615cc85f395f51905f528152f35b63703e46dd60e11b5f5260045ffd5b6040366003190112611ad9576124bf612ead565b602435906001600160401b038211611ad95736602383011215611ad9578160040135906124eb8261300f565b916124f96040519384612e75565b80835260208301933660248383010111611ad957815f926024602093018737840101526001600160a01b037f000000000000000000000000c4a24a83c92fa5ecc5207c71ac62dcd26709ad8e16308114908115612694575b5061249c5761255e613840565b6040516352d1902d60e01b81526001600160a01b0382169390602081600481885afa5f9181612660575b506125a05784634c9c8ce360e01b5f5260045260245ffd5b805f516020615cc85f395f51905f5286920361264e5750823b1561263c575f516020615cc85f395f51905f5280546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a2825115612623575f8091612621945190845af461261b614c36565b91614ddc565b005b5050503461262d57005b63b398979f60e01b5f5260045ffd5b634c9c8ce360e01b5f5260045260245ffd5b632a87526960e21b5f5260045260245ffd5b9091506020813d60201161268c575b8161267c60209383612e75565b81010312611ad957519086612588565b3d915061266f565b5f516020615cc85f395f51905f52546001600160a01b03161415905084612551565b34611ad95760e0366003190112611ad95760206127076126d4612ec3565b6126dc612fa1565b6126e4612ff9565b6126ec612fb7565b6126f4612f56565b916126fd612f65565b9360c435956130bf565b6001600160401b0360405191168152f35b34611ad9575f366003190112611ad957612730613840565b5f516020615d085f395f51905f525460ff8116156127875760ff19165f516020615d085f395f51905f52557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1005b638dfc202b60e01b5f5260045ffd5b34611ad9576020366003190112611ad9576126216127b2612ead565b6127ba613840565b613052565b34611ad9576080366003190112611ad9576004356001600160401b038111611ad95736602382011215611ad95780600401356127fa81612e96565b916128086040519384612e75565b8183526024602084019260051b82010190368211611ad957602401915b818310612df557836024356001600160401b038111611ad95761284c903690600401612ed9565b90612855612f47565b916064354211611b095761286761379e565b61286f6137d6565b8151815103612de6578215155f5b8351811015612dd3576001600160a01b03612898828661302a565b5116906128a5818561302a565b51916001600160401b038316926128bb82613873565b93825f52600a60205260ff600160405f20015460801c168015612dca575b15612dbb576001808316149160281c62ffffff1682612dae575b620fffff81169060141c600f1681151580612da1575b15612d9257604d8111612367576001600160481b0390600a0a1602946001600160481b038616958603612367575f8315612c6f578a15612bf0575060048054604080516347ca7d2960e11b81526001600160401b038681169482019490945293909216602484015291939291849060449082905f906001600160a01b03165af180156120c3575f935f91612bcc575b5092915f915b6129ac886109b785876137fd565b976129c06129b98a614256565b859a6137fd565b945b600654608081901c6001600160401b031694905f8615612afc575050506001600160801b0391610a06866129f5936137fd565b1691805f19048311810215670de0b6b3a76400000215611ad95780612a28670de0b6b3a7640000612a2e938602046141ea565b936136e5565b916001600160801b03811694670de0b6b3a7640000860295808704670de0b6b3a76400001490151715612367575f516020615c885f395f51905f5260c0612ab7946001600160801b03612a85819a612ac099613673565b9a5b604051928352166020820152888d166040820152888416606082015288851660808201528d60a0820152a1613680565b93600b54613759565b600b5516158015612af3575b15612ae45760019384612ade9361428d565b0161287d565b6396e6bb8760e01b5f5260045ffd5b50813314612acc565b9395509691939097612b17612b1188876137fd565b8761381d565b946001600160801b03612b2987614256565b1690670de0b6b3a7640000820297828904670de0b6b3a7640000148315171561236757612b77612ac0996001600160801b03610bc5612ab79b829f6001600160401b039060401c169061381d565b9b15612b99575b5050505f516020615c885f395f51905f52918860c092612a87565b60c09396505f516020615c885f395f51905f529492610c24610c1e610c198e95612bc29561381d565b9592829450612b7e565b9050612be791935060403d8111610c7757610c668183612e75565b9290928b612998565b6004805460408051631f43d3d960e31b81526001600160401b0387811694820194909452949092166024850152919491839060449082905f906001600160a01b03165af180156120c3575f925f91612c4b575b50919261299e565b9050612c6691925060403d8111610c7757610c668183612e75565b9190918c612c43565b8a15612d115750600554604080516347ca7d2960e11b81526001600160401b0360018617811660048301529093166024840152919392919084906001600160a01b0316815f816044810103925af180156120c3575f935f91612ced575b5092915f915b612cdc83856137fd565b97612ce7818561381d565b946129c2565b9050612d0891935060403d8111610c7757610c668183612e75565b9290928b612ccc565b60055460408051631f43d3d960e31b81526001600160401b03600187178116600483015290941660248501529194919083906001600160a01b0316815f816044810103925af180156120c3575f925f91612d6e575b509192612cd2565b9050612d8991925060403d8111610c7757610c668183612e75565b9190918c612d66565b63a25f85b760e01b5f5260045ffd5b50620f423f821115612909565b62ffffff908103166128f3565b6326831c8760e21b5f5260045ffd5b508233146128d9565b60015f516020615d285f395f51905f5255005b63512509d360e11b5f5260045ffd5b82356001600160a01b0381168103611ad957815260209283019201612825565b34611ad9575f366003190112611ad9576007546001600160a01b038116825260a01c60ff1615156020820152604090f35b608081019081106001600160401b03821117612e6157604052565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b03821117612e6157604052565b6001600160401b038111612e615760051b60200190565b600435906001600160a01b0382168203611ad957565b600435906001600160401b0382168203611ad957565b9080601f83011215611ad957813590612ef182612e96565b92612eff6040519485612e75565b82845260208085019360051b820101918211611ad957602001915b818310612f275750505090565b82356001600160401b0381168103611ad957815260209283019201612f1a565b604435908115158203611ad957565b608435908115158203611ad957565b60a435908115158203611ad957565b600435908115158203611ad957565b60c435908115158203611ad957565b602435908115158203611ad957565b602435906001600160801b0382168203611ad957565b606435906001600160801b0382168203611ad957565b600435906001600160801b0382168203611ad957565b608435906001600160801b0382168203611ad957565b604435906001600160481b0382168203611ad957565b6001600160401b038111612e6157601f01601f191660200190565b805182101561303e5760209160051b010190565b634e487b7160e01b5f52603260045260245ffd5b6008546001600160a01b03828116929082168381146130b957604080516001600160a01b0393841681529190921660208201527f95bb211a5a393c4d30c3edc9a745825fba4e6ad3e3bb949e6bf8ccdfe431a8119190a16001600160a01b03191617600855565b50505050565b9594919390926130cd6137d6565b5f9660016001600160401b03821611613189575b6001600160801b0385166130fa575b5050505050505090565b60019192939495969750811614954211611b095761317d9461314d9461311e6137d6565b8760405161312b81612e46565b5f81525f60208201525f60408201525f606082015261314861379e565b613f0f565b9160015f516020615d285f395f51905f52556001600160801b0360206001600160401b0385511694015116613f44565b5f8080808080806130f0565b864211611b095761319861379e565b6131a06137d6565b5f6131aa33613873565b335f818152600a602052604090206001015460801c60ff16801561366a575b15612dbb576001808516148062ffffff8660281c169061365d575b620fffff81169060141c600f1681151580613650575b15612d9257604d8111612367576001600160481b0390600a0a1602926001600160481b038416938403612367575f82156135b057851561352f575060048054604080516347ca7d2960e11b81526001600160401b038a81169482019490945293909216602484015291959392918690604490829087906001600160a01b03165af1801561352457839584916134ff575b50949083915b61329e866109b785846137fd565b956132b26132ab88614256565b85986137fd565b915b600654608081901c6001600160401b031694908890861561341b575050506001600160801b0391610a06866132e8936137fd565b1691805f19048311810215670de0b6b3a764000002156108445780612a28670de0b6b3a764000061331b938602046141ea565b6001600160801b03831690670de0b6b3a7640000820291808304670de0b6b3a7640000149015171561340757926133b8925f516020615c885f395f51905f5260c08c6001600160801b036133746133af97829b9a613673565b9d5b6001600160401b0360405193168352166020820152888c166040820152888416606082015288851660808201528a60a0820152a1613680565b96600b54613759565b600b5516159081156133fd575b50156133ee5750906133d891863361428d565b60015f516020615d285f395f51905f52556130e1565b6396e6bb8760e01b8152600490fd5b905033145f6133c5565b634e487b7160e01b87526011600452602487fd5b92919a9390955061342f610b5788846137fd565b926001600160801b0361344185614256565b1693670de0b6b3a7640000850291858304670de0b6b3a764000014861517156134eb57938e936134966133af98946001600160801b03610bc5819e9d9a966001600160401b036133b89e9b60401c169061381d565b9e156134b8575b5050505f516020615c885f395f51905f52918860c092613376565b60c09396505f516020615c885f395f51905f529492610c24610c1e610c198e956134e19561381d565b959282945061349d565b634e487b7160e01b8c52601160045260248cfd5b905061351b91955060403d604011610c7757610c668183612e75565b9490945f61328a565b6040513d85823e3d90fd5b6004805460408051631f43d3d960e31b81526001600160401b038b8116948201949094529490921660248501529196949391839060449082905f906001600160a01b03165af180156120c3575f925f9161358b575b5091613290565b90506135a791925060403d604011610c7757610c668183612e75565b9190915f613584565b60055460408051631f43d3d960e31b81526001600160401b0360018b1781166004830152909416602485015291965091945f9493909290919086906001600160a01b03168187816044810103925af19485156120c3575f905f9661362c575b5085926136268161362089856137fd565b9861381d565b916132b4565b905061364891955060403d604011610c7757610c668183612e75565b94905f61360f565b50620f423f8211156131fa565b62ffffff908103166131e4565b508033146131c9565b9190820391821161236757565b906001600160801b03809116911601906001600160801b03821161236757565b90600160401b600160c01b0382549160401b1690600160401b600160c01b031916179055565b90816020910312611ad957516001600160a01b0381168103611ad95790565b8181029291811591840414171561236757565b9360c095919897969360ff9360e087019a60018060a01b0316875260018060a01b031660208701526040860152606085015216608083015260a08201520152565b906001600160401b03809116911601906001600160401b03821161236757565b9190820180921161236757565b51906001600160801b0382168203611ad957565b9190826040910312611ad95761379b602061379484613766565b9301613766565b90565b60025f516020615d285f395f51905f5254146137c75760025f516020615d285f395f51905f5255565b633ee5aeb560e01b5f5260045ffd5b60ff5f516020615d085f395f51905f5254166137ee57565b63d93c066560e01b5f5260045ffd5b906001600160801b03809116911603906001600160801b03821161236757565b906001600160801b03809116911602906001600160801b03821691820361236757565b5f516020615ca85f395f51905f52546001600160a01b0316330361386057565b63118cdaa760e01b5f523360045260245ffd5b6001600160a01b03165f818152600a60205260409020546001600160401b03169190821561389e5750565b9150600954916001600160401b0383166001600160401b0381146123675767ffffffffffffffff199384166001600160401b0360019283019081169182176009555f938452600a6020526040909320805490951617845592909201805460ff60801b1916600160801b179055565b5f516020615d685f395f51905f5280546001600160a01b03199081169091555f516020615ca85f395f51905f5280549182166001600160a01b0393841690811790915591167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3565b6040516370a0823160e01b815230600482015291926001600160a01b0382169190602084602481865afa9384156120c3575f94613a79575b50602494602093926139fe92604051926323b872dd60e01b8785015260018060a01b03168884015260018060a01b03166044830152876064830152606482526139f9608483612e75565b614d44565b6040516370a0823160e01b815230600482015293849182905afa80156120c3575f90613a45575b613a2f9250613673565b03613a3657565b632f35253160e01b5f5260045ffd5b506020823d602011613a71575b81613a5f60209383612e75565b81010312611ad957613a2f9151613a25565b3d9150613a52565b9093506020929192813d602011613aac575b81613a9860209383612e75565b81010312611ad957519290919060246139af565b3d9150613a8b565b90816020910312611ad957518015158103611ad95790565b81613b3a575b6001600160a01b031680156120eb5760405160408101928184106001600160401b03851117612e6157602093604052828252151592839101526001600160601b0360a01b60075416176007556007549060ff60a01b9060a01b169060ff60a01b191617600755565b6040516301ffc9a760e01b8152630920cbe360e31b60048201526020816024816001600160a01b0386165afa9081156120c3575f91613b88575b50613ad2576309bfcb9b60e31b5f5260045ffd5b613baa915060203d602011613bb0575b613ba28183612e75565b810190613ab4565b5f613b74565b503d613b98565b90816020910312611ad957516001600160401b0381168103611ad95790565b6001600160401b0390911681526001600160801b03909116602082015260400190565b6001600160401b039182168152911660208201526001600160801b0391821660408201529116606082015260800190565b9594929391928691906001600160801b03851680151580613efd575b15613eef5734158015613ec3575b15613eb457613c66836112dd896140fc565b5f9390849081808415613e3a5750506005546040805163a558898f60e01b81529a90928b926001600160a01b03169183915f918391613ca9919060048401613bd6565b03925af19586156120c3575f985f97613e13575b50868997985b6001600160801b03613cde613cd784614c8c565b8096613680565b9b169182613d93575b6001600160801b03613d146060968280948760208a0152169687604082015283821698899101525f613680565b9216911611613d84576001600160481b03613d829b604051965f885260208801521660408601525f60608601525f608086015260a085015260c084015260e083015260016101008301525f6101208301521515905f516020615d885f395f51905f526101403392a33361468c565b565b6352866ea560e11b5f5260045ffd5b60405163371da77d60e01b81526020816004817f000000000000000000000000b9d597d00627a6e451ba8c08fe7277f08533cc536001600160a01b03165afa9081156120c3575f91613df4575b50613ce75763ab655c5560e01b5f5260045ffd5b613e0d915060203d602011613bb057613ba28183612e75565b5f613de0565b909650613e3091985060403d604011610c7757610c668183612e75565b979097955f613cbd565b979650979150613e6f9860409160018060a01b0360045416905f8451809d8195829463a558898f60e01b845260048401613bd6565b03925af19485156120c3575f985f96613e8d575b5085899692613cc3565b909550613eaa91985060403d604011610c7757610c668183612e75565b979097945f613e83565b6328745eb160e01b5f5260045ffd5b5060035460ff8160a01c169081613edb575b50613c54565b60ff915060a81c161515831515145f613ed5565b62f8653360e71b5f5260045ffd5b506001600160481b0387161515613c46565b613f2196610120525f61014052614e3a565b6101405190565b9096613f3e976101005260c0525f60e052615544565b60e05190565b6001600160801b031615613fa75760075460ff8160a01c1680613fb4575b613f6a575050565b6001600160a01b031690813b15611ad9575f91602483926040519485938492630920cbe360e31b8452151560048401525af180156120c357613faa575b50565b5f613d8291612e75565b50336001600160a01b0382161415613f62565b8115613fd1570490565b634e487b7160e01b5f52601260045260245ffd5b600b545f19810181811161236757670de0b6b3a7640000900490670de0b6b3a7640000820290821591838104670de0b6b3a7640000148317156123675761402b91613673565b600b55613fa75761409061407e60018060a01b035f516020615ca85f395f51905f5254169261407261406b6001600160401b0360055460a01c1683614daf565b8092613673565b806140af575b506141ea565b6001600160801b0360015491166136e5565b80614099575050565b600354613d8292906001600160a01b031661421b565b6140b8906141ea565b60018060a01b03600754165f52600a6020526001600160801b036140e6600160405f20019282845416613680565b166001600160801b03198254161790555f614078565b906001600160481b0382168015159081614191575b5015614182575f915b6001600160481b03811690620f423f82111561416a57506001600160481b03600a82061661415b57600a60ff9104921660ff8114612367576001019161411a565b632f17742b60e21b5f5260045ffd5b62f00000915062ffffff90939293169160141b161790565b6323f5f0b960e11b5f5260045ffd5b683635c6204739d98000915011155f614111565b67fffffffffffffffe906001925f146141cd5760271b677fffff8000000000165b821b161890565b62ffffff67ffffff8000000000911662ffffff0360271b166141c6565b6001600160801b038111614204576001600160801b031690565b6306dfcc6560e41b5f52608060045260245260445ffd5b60405163a9059cbb60e01b60208201526001600160a01b039092166024830152604480830193909352918152613d82916139f9606483612e75565b6001600160401b0360065460401c169081156142875761379b916001600160801b036142829216614daf565b6141ea565b50505f90565b9091925f80945f945f916003549660ff8860a81c1697885f1461467d57506002546001600160a01b0316975b34614601575b50906001600160801b031680156145f157821561459e576001600160801b03916142ee6142f4925f54906136e5565b90613759565b945b16908115614596571561453557906142ee61431492600154906136e5565b915b60035460ff8160a01c1661447d575b50918183819461442b575b5061440b575b806143bf575b506143a1575b50504761434d575050565b47906001600160a01b0316803b15610848578290600460405180948193630d0e30db60e41b83525af1801561439657614384575050565b61438f828092612e75565b6103395750565b6040513d84823e3d90fd5b6003546143b89230916001600160a01b0316613977565b5f82614342565b600354908460ff8360a01c16806143fd575b156143e6576143e09250614c65565b5f61433c565b6143f8926001600160a01b031661421b565b6143e0565b5060ff8360a81c16156143d1565b600254614426908390309087906001600160a01b0316613977565b614336565b60035460ff8160a01c16908161446f575b50156144525761444c9086614c65565b5f614330565b60025461446a919087906001600160a01b031661421b565b61444c565b60ff915060a81c165f61443c565b5f9060a81c60ff16808061452c575b61451a575b1580614511575b614501575b8015614325579091506001600160a01b03851690813b15611ad9575f91602483926040519485938492632e1a7d4d60e01b845260048401525af180156120c3576144ea575b908591614325565b6144f8919295505f90612e75565b5f93905f6144e2565b5061450c4784613673565b61449d565b50478411614498565b90506145264783613673565b90614491565b5047831161448c565b5f516020615c685f395f51905f52604060018060a09795971b03871692835f52600a6020526001825f20016001600160801b036145758382845416613680565b166001600160801b03198254161790558151905f82526020820152a2614316565b505091614316565b946001600160801b0391955f516020615c685f395f51905f52604060018060a01b038a1692835f52600a6020526145e0825f2061107483898354871c16613680565b81519081525f6020820152a26142f6565b50936001600160801b03906142f6565b1561464657506001600160801b0361463d6146365f546146306146276142828334613fc7565b918583166136e5565b94613680565b9234613673565b915b91906142bf565b9092506001600160801b0361467761467060015461466a6146276142828334613fc7565b98613680565b9634613673565b9361463f565b6001600160a01b0316976142b9565b92919390945f955f905f925f925f966003549960ff8b60a81c169a8b5f14614bfc57506002546001600160a01b03169a5b34614b94575b506001600160801b0382166001600160801b0382168181115f14614aaa575050036001600160801b03168315614a5857906142ee614703925f54906136e5565b945b6001600160801b0382166001600160801b0382168181115f14614964575050036001600160801b0316901561490357906142ee61474592600154906136e5565b915b60035460ff8160a01c16614858575b5080614806575b50806147e6575b508061479a575b508061477c5750504761434d575050565b6003546147939230916001600160a01b0316613977565b5f80614342565b600354908360ff8360a01c16806147d8575b156147c1576147bb9250614c65565b5f61476b565b6147d3926001600160a01b031661421b565b6147bb565b5060ff8360a81c16156147ac565b6002546148009190309086906001600160a01b0316613977565b5f614764565b60035460ff8160a01c16908161484a575b501561482d576148279085614c65565b5f61475d565b600254614845919086906001600160a01b031661421b565b614827565b60ff915060a81c165f614817565b5f9060a81c60ff1680806148fa575b6148e8575b15806148df575b6148cf575b8015614756576001600160a01b03871690813b15611ad9575f91602483926040519485938492632e1a7d4d60e01b845260048401525af180156120c35715614756576148c79197505f90612e75565b5f955f614756565b506148da4784613673565b614878565b50478411614873565b90506148f44783613673565b9061486c565b50478311614867565b5f516020615c685f395f51905f52604060018060a09795971b03881692835f52600a6020526001825f20016001600160801b036149438382845416613680565b166001600160801b03198254161790558151905f82526020820152a2614747565b909192935095939510614979575b5050614747565b6001600160a01b0387165f818152600a602052604090206001015490926001600160801b0392900382169116818110614a00575060405f516020615ce85f395f51905f5291835f52600a6020526001825f20016001600160801b038083818454160316166001600160801b03198254161790558151905f82526020820152a25b5f80614972565b95506040614a2a5f516020615ce85f395f51905f52926001600160801b03896001549203166136e5565b96835f52600a6020526001825f20016001600160801b031981541690558151905f82526020820152a26149f9565b5f516020615c685f395f51905f52604060018060a09a959a1b038b1692835f52600a602052614a99825f20611074836001600160801b038354871c16613680565b81519081525f6020820152a2614705565b98939810614aba575b5050614705565b6001600160801b0391031660018060a01b03891690815f52600a6020526001600160801b0360405f205460401c16818110155f14614b3d575060405f516020615ce85f395f51905f5291835f52600a602052614b29825f206001600160801b0383818354871c160316906136a0565b81519081525f6020820152a25b5f80614ab3565b96506040614b665f516020615ce85f395f51905f52926001600160801b038a5f549203166136e5565b97835f52600a602052815f20600160401b600160c01b0319815416905581519081525f6020820152a2614b36565b90929015614bcd5750614bc56146365f54614630614bb56142828334613fc7565b916001600160801b0383166136e5565b915b5f6146c3565b919450614bf6614bef600154614be9614bb56142828334613fc7565b99613680565b9734613673565b94614bc7565b6001600160a01b03169a6146bd565b60ff5f516020615d485f395f51905f525460401c1615614c2757565b631afcd79f60e31b5f5260045ffd5b3d15614c60573d90614c478261300f565b91614c556040519384612e75565b82523d5f602084013e565b606090565b5f80809381935af1614c75614c36565b5015614c7d57565b6312171d8360e31b5f5260045ffd5b6001600160801b03168015614d3f576006546001600160401b038160801c16916001600160401b03614cc084828516613739565b168015614d3757614cd19082614daf565b91670de0b6b3a7640000830290838204670de0b6b3a76400001484151715612367576142ee836001600160401b03614d1c614d2795614d1661379b9a614d2f996136e5565b90613673565b9360401c16906136e5565b600b54613759565b600b556141ea565b505050505f90565b505f90565b5f80614d6c9260018060a01b03169360208151910182865af1614d65614c36565b9083614ddc565b8051908115159182614d94575b5050614d825750565b635274afe760e01b5f5260045260245ffd5b614da79250602080918301019101613ab4565b155f80614d79565b815f19048111820215670de0b6b3a76400000215611ad95702670de0b6b3a7640000808204910615150190565b90614e005750805115614df157805190602001fd5b630a12f52160e11b5f5260045ffd5b81511580614e31575b614e11575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b15614e09565b9491939492909280610140525f916001600160801b038616151580615532575b15613eef5734159687159788615506575b15613eb4578492614e7b836140fc565b98614e86888b6141a5565b94615377575b50505f6101808190526101a08190526101c0819052978893849384939188156151a0575b505f99614ebd85826137fd565b925f946001600160801b038516614fae575b506001600160801b0380614ee38a88613680565b9216911611614f9f576040519a6001600160401b03168b526001600160801b031660208b01526001600160481b031660408a01526001600160801b031660608901526001600160801b031660808801526001600160801b031660a08701526001600160801b031660c08601526001600160801b031660e0850152610100840152151561012083015215159033906101405f516020615d885f395f51905f5291a36101c0516101a0516101805161012051613d829491903361468c565b6352866ea560e11b8852600488fd5b9194509b9a50600854906001600160401b03808360a01c16928160a01b5f19850160a01b16908260a01b1916178060085560a01c161561519157677fffff8000000000908b156151865762ffffff0360271b1617925b600167fffffffffffffffe85821b16189a61501e33613873565b6150316001600160481b0385168661381d565b6101605261504161016051614256565b958c156150e557506004546001600160a01b0316803b156150e157615088918b918f83899160405196879586948593635919321160e11b8552610160519260048601613bf9565b03925af180156150d65785918b916150bd575b50506150a691613680565b9b5b6001600160401b038c1661014051525f614ecf565b819250906150ca91612e75565b610b3f5783895f61509b565b6040513d8c823e3d90fd5b8a80fd5b600554929e9d90926001600160a01b031691823b15611ad95761512892875f809460405196879586948593635919321160e11b8552610160519260048601613bf9565b03925af180156120c357615169575b5067fffffffffffffffe9060011b169a6151606151578661016051613680565b6101c051613680565b6101c0526150a8565b6151769199505f90612e75565b5f9767fffffffffffffffe615137565b60271b161792615004565b63888ea83960e01b5f5260045ffd5b93509450925097865f146152fc57506040876151de9260018060a01b0360055416905f845180968195829463a558898f60e01b845260048401613bd6565b03925af19788156120c3575f915f996152d9575b50889282996101a0525b61520584614c8c565b94615213866101c051613680565b6101c0526001600160801b03841680615259575b60206101405101526001600160801b03851660406101405101526001600160801b03861660606101405101525f614eb0565b60405163371da77d60e01b81526020816004817f000000000000000000000000b9d597d00627a6e451ba8c08fe7277f08533cc536001600160a01b03165afa9081156120c3575f916152ba575b506152275763ab655c5560e01b5f5260045ffd5b6152d3915060203d602011613bb057613ba28183612e75565b5f6152a6565b9098506152f5915060403d604011610c7757610c668183612e75565b975f6151f2565b9760408861532c9360018060a01b0360045416905f845180978195829463a558898f60e01b845260048401613bd6565b03925af19283156120c3575f925f94615350575b508383610180526101c0526151fc565b90935061536d91925060403d604011610c7757610c668183612e75565b919091925f615340565b5f881561549357600554604051632e28668360e01b815290602090829060049082906001600160a01b03165afa80156120c3576001600160401b03915f91615464575b50166001600160401b038716111561545c575b15614e8c57935097505091506001600160481b03925061544d575b6001600160801b03604051945f86521660208501521660408301525f60608301525f60808301525f60a08301525f60c08301525f60e08301525f61010083015260016101208301521515905f516020615d885f395f51905f526101403392a361014052565b6154573433614c65565b6153e8565b5060016153cd565b615486915060203d60201161548c575b61547e8183612e75565b810190613bb7565b5f6153ba565b503d615474565b60048054604051632e28668360e01b81529160209183919082906001600160a01b03165afa80156120c3576001600160401b03915f916154e7575b50166001600160401b038716116153cd575060016153cd565b615500915060203d60201161548c5761547e8183612e75565b5f6154ce565b5060035460ff8160a01c16908161551e575b50614e6b565b60ff915060a81c161515861515145f615518565b506001600160481b0381161515614e5a565b939291909594958460e052831584615c5f575b15615c50575f916001600160801b038216151580615c3e575b15613eef5734159182159283615c0f575b15613eb4578896615591836140fc565b9361559f61010051866141a5565b9a615a86575b50505f6101608190526101a081905260808190526101c081905298899586959189156158a8575b505f61018052876158a1576155e186846137fd565b945b5f60a0526001600160801b0386166156ca575b506001600160801b038061560c8d60a051613680565b92169116116156bb57506001600160801b0397989388809693946001600160481b038296839560206040519e8f926001600160401b0361018051168452169101521660408c01521660608a01528160a0511660808a01521660a08801521660c08601521660e084015215156101008301521515610120820152610100511515905f516020615d885f395f51905f526101403392a3613d826101c0516101a0516080516101605160c0513361468c565b6352866ea560e11b8152600490fd5b600854906001600160401b03808360a01c16928160a01b5f19850160a01b16908260a01b1916178060085560a01c161561519157677fffff800000000090610100515f146158975762ffffff0360271b16175b600167fffffffffffffffe82821b16186101805261573a33613873565b610120526157516001600160481b0386168761381d565b6101405261576161014051614256565b60a05261010051156157fd57506004546001600160a01b0316803b1561084857826040518092635919321160e11b82528183816157ad610140518d610180516101205160048601613bf9565b03925af18015613524579083916157e8575b50506157cd85608051613680565b6080525b6001600160401b03610180511660e051525f6155f6565b816157f291612e75565b61087057815f6157bf565b6005546001600160a01b0316803b15611ad9575f6040518092635919321160e11b825281838161583d8d6101405190610180516101205160048601613bf9565b03925af180156120c35761587a575b5067fffffffffffffffe9060011b166101805261587161515760a05161014051613680565b6101c0526157d1565b6158879193505f90612e75565b5f9167fffffffffffffffe61584c565b60271b161761571d565b5f946155e3565b955099509450610100515f14615a07576040816158e79560018060a01b0360055416905f845180998195829463a558898f60e01b845260048401613bd6565b03925af19485156120c3575f945f966159e0575b5085856080526101a0525b61590f86614c8c565b9961591d8b6101c051613680565b6101c0526001600160801b03861680615960575b602060e05101526001600160801b038716604060e05101526001600160801b038b16606060e05101525f6155cc565b60405163371da77d60e01b81526020816004817f000000000000000000000000b9d597d00627a6e451ba8c08fe7277f08533cc536001600160a01b03165afa9081156120c3575f916159c1575b506159315763ab655c5560e01b5f5260045ffd5b6159da915060203d602011613bb057613ba28183612e75565b5f6159ad565b9095506159fd91945060403d604011610c7757610c668183612e75565b939093945f6158fb565b600480546040805163a558898f60e01b815296909287926001600160a01b03169183915f918391615a3b9189918401613bd6565b03925af19485156120c3575f945f96615a5f575b508585610160526101c052615906565b909550615a7c91945060403d604011610c7757610c668183612e75565b939093945f615a4f565b5f610100515f14615b9c57600554604051632e28668360e01b815290602090829060049082906001600160a01b03165afa80156120c3576001600160401b03915f91615b7d575b50166001600160401b038d161115615b75575b156155a557945097985095509250506001600160481b039250615b66575b6001600160801b03604051935f85521660208401521660408201525f60608201525f60808201525f60a08201525f60c08201525f60e08201525f6101008201526001610120820152610100511515905f516020615d885f395f51905f526101403392a360e052565b615b703433614c65565b615afe565b506001615ae0565b615b96915060203d60201161548c5761547e8183612e75565b5f615acd565b60048054604051632e28668360e01b81529160209183919082906001600160a01b03165afa80156120c3576001600160401b03915f91615bf0575b50166001600160401b038d1611615ae057506001615ae0565b615c09915060203d60201161548c5761547e8183612e75565b5f615bd7565b5060035460ff8160a01c169081615c27575b50615581565b60ff915060a81c161515610100511515145f615c21565b506001600160481b0381161515615570565b639aa6df0360e01b5f5260045ffd5b50861561555756fe91a0eb2c39ca4d8b85d038e494302fb14bda4920d009c0aa44f26960104adb97921a8ce27b6521c36c2f7901104535739cfb9dc28cd1bca46f5fe5913f0d079d9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc46a85bb068360778f28161eb8ac970939d29cc684f100323a8e5f120adc45ff1cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00f0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c007cbbf9e533e963aebd385f66fc01e69558a4fe08eb6c6bc0127fa292b0442800a2646970667358221220d6c6dd7d00db3d8928d1597ced112522ac59ce7379c0dc88729955f7d184034c64736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000b9d597d00627a6e451ba8c08fe7277f08533cc53
-----Decoded View---------------
Arg [0] : _watch_dog (address): 0xB9D597D00627A6E451ba8C08fE7277f08533CC53
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000b9d597d00627a6e451ba8c08fe7277f08533cc53
Deployed Bytecode Sourcemap
2951:56759:28:-:0;;;;;;;;;;-1:-1:-1;2951:56759:28;;;;;;;;;11313:19;2951:56759;;;;;;11313:187;;;;2951:56759;;;;;;;;;;-1:-1:-1;2951:56759:28;;-1:-1:-1;2951:56759:28;11313:187;2951:56759;;;;;;;;;;11368:49;;11313:187;11367:119;;;;11313:187;;;;;;11367:119;11435:16;;-1:-1:-1;11435:16:28;:50;;11367:119;;;;;;11435:50;-1:-1:-1;;;;;2951:56759:28;11455:10;:30;;-1:-1:-1;11435:50:28;;;11368:49;11409:7;2951:56759;-1:-1:-1;;;;;2951:56759:28;11387:10;:30;;-1:-1:-1;11368:49:28;;2951:56759;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;:::i;:::-;;;;:::i;:::-;;;;5100:15;:25;5096:79;;2281:72:5;3282:1:6;2281:72:5;;;;:::i;:::-;2951:56759:28;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;3217:103:6;;:::i;:::-;3282:1;:::i;:::-;4304:2:28;2951:56759;-1:-1:-1;;;;;;;;;;;4304:2:28;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;15829:22;-1:-1:-1;;;;;2951:56759:28;15829:22;;2951:56759;;15878:21;16011:5;-1:-1:-1;;;;;2951:56759:28;15878:21;2951:56759;15878:21;;2951:56759;;15926:21;;2951:56759;;16011:5;;;:::i;:::-;2951:56759;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;;;;;;5096:79;-1:-1:-1;;;5148:16:28;;2951:56759;5148:16;;2951:56759;;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;2303:62:1;;:::i;:::-;-1:-1:-1;;;;;;;;;;;2951:56759:28;;-1:-1:-1;;;;;;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;;2238:43:0;;;;2951:56759:28;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;;;:::i;:::-;;;-1:-1:-1;;;;;2951:56759:28;;;;;;3217:103:6;;:::i;:::-;2281:72:5;;:::i;:::-;2345:1;31604:34:28;;31648;31726:10;;2951:56759;;31718:7;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;;;;;;31726:10;2951:56759;;31718:7;2951:56759;;-1:-1:-1;;;;;31779:27:28;2951:56759;;;31779:27;2951:56759;;31817:118;;;2951:56759;-1:-1:-1;;;;;2951:56759:28;;31949:18;;31945:327;;2951:56759;;;-1:-1:-1;;;;;2951:56759:28;;32286:18;;32282:325;;2951:56759;32658:26;;;32904:53;32658:26;;-1:-1:-1;;;;;;;;;;;32658:26:28;32654:113;;2951:56759;32780:26;;32776:113;;2951:56759;-1:-1:-1;2951:56759:28;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;31726:10;;2951:56759;;;;;;;32904:53;;;;31779:27;-1:-1:-1;;;;;;;;;;;4304:2:28;2951:56759;;32776:113;32822:7;2951:56759;32855:22;;31726:10;;;-1:-1:-1;;;;;2951:56759:28;32855:22;:::i;:::-;32776:113;;;32654;32700:7;2951:56759;32733:22;;31726:10;;;-1:-1:-1;;;;;2951:56759:28;32733:22;:::i;:::-;32654:113;;;32282:325;32328:31;;;;;;;2951:56759;;31726:10;49151:30;-1:-1:-1;;;;;;;;;;;31726:10:28;;32904:53;31726:10;;2951:56759;;31718:7;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;31779:27;2951:56759;;;32438:27;2951:56759;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;31779:27;2951:56759;49151:30;;:::i;:::-;32282:325;;;;;;;2951:56759;-1:-1:-1;;;2951:56759:28;;;;;31945:327;31991:32;;;;;;;2951:56759;;31726:10;32102:61;-1:-1:-1;;;;;31726:10:28;48658:30;31726:10;;2951:56759;;31718:7;2951:56759;;;;;;;32102:61;:::i;:::-;2951:56759;;48658:30;;:::i;:::-;31945:327;;;;;2951:56759;-1:-1:-1;;;2951:56759:28;;;;;31817:118;31849:31;-1:-1:-1;31849:31:28;-1:-1:-1;31849:31:28;;31817:118;;2951:56759;;;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;:::i;:::-;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;:::i;:::-;;;;:::i;:::-;;;;5100:15;;;:25;5096:79;;2281:72:5;;:::i;:::-;2951:56759:28;;;;27373:37;;:74;;;;2951:56759;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;-1:-1:-1;;2951:56759:28;;;;27570:10;27604:3;2951:56759;;27582:20;;;;;27671:12;25706:15;27671:12;;;;;;-1:-1:-1;;;;;27732:9:28;27671:12;-1:-1:-1;;;;;27701:13:28;27671:12;;-1:-1:-1;;;;;2951:56759:28;27671:12;;;;;:::i;:::-;2951:56759;;27701:13;;:::i;:::-;2951:56759;;27732:9;;:::i;:::-;2951:56759;;25706:15;;:::i;:::-;-1:-1:-1;;;;;27623:259:28;;;;:::i;:::-;2951:56759;;;;;27570:10;;27582:20;;;;2951:56759;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;-1:-1:-1;2951:56759:28;;;;;;;;;;;;;;-1:-1:-1;;;2951:56759:28;;;;;27373:74;2951:56759;;;;27414:33;27373:74;;;5096:79;-1:-1:-1;;;5148:16:28;;2951:56759;5148:16;;2951:56759;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;;;:::i;:::-;;;;:::i;:::-;;;;5100:15;:25;5096:79;;3217:103:6;;:::i;:::-;2281:72:5;;:::i;:::-;49886:27:28;23822:10;49886:27;:::i;:::-;23822:10;;2951:56759;;49931:7;2951:56759;;;;;;;49931:24;2951:56759;;;;49931:49;;;;2951:56759;;;;;34551:22;;;34550:31;2951:56759;;;;;;34662:123;;;2951:56759;1216:7:21;1212:11;;;1181:2;2951:56759:28;;;1243:5:21;;;;:20;;2951:56759:28;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;49931:7;2951:56759;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;50093:17;;;50210:34;50255:1171;;;;;50280:371;;;;-1:-1:-1;2951:56759:28;4373:4;;2951:56759;;;-1:-1:-1;;;50399:42:28;;-1:-1:-1;;;;;2951:56759:28;;;50399:42;;;2951:56759;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;50399:42;;;;;;;-1:-1:-1;;50399:42:28;;;50280:371;50355:86;50460:30;50508:17;;50280:371;;50702:38;50703:28;;;;;:::i;:::-;50702:38;:::i;:::-;50769:48;50883:21;50769:48;;;:::i;:::-;50832:25;50883:21;;:::i;:::-;50255:1171;;45165:25;2951:56759;;;;;-1:-1:-1;;;;;2951:56759:28;;;45101:20;;45165:29;;2951:56759;;45244:28;;;-1:-1:-1;;;;;45244:28:28;;;45235:38;45244:28;;:::i;:::-;45235:38;;:::i;:::-;2951:56759;1744:340:19;;;;;;;;;;4373:4:28;1744:340:19;;;;;45393:26:28;4373:4;45454:42;1744:340:19;;;;45393:26:28;:::i;:::-;45454:42;;:::i;:::-;-1:-1:-1;;;;;2951:56759:28;;;4373:4;2951:56759;;;;;;4373:4;2951:56759;;;;;;;;51726:27;45454:63;-1:-1:-1;;;;;45454:63:28;;;;;51763:38;45454:63;;-1:-1:-1;;;;;;;;;;;45454:63:28;;:::i;:::-;45161:974;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51620:96;51726:27;:::i;:::-;2951:56759;51763:38;2951:56759;51763:38;:::i;:::-;;4304:2;2951:56759;51821:18;51820:45;;;;45161:974;2951:56759;;;51912:72;23822:10;;;51912:72;:::i;:::-;2951:56759;-1:-1:-1;;;;;;;;;;;4304:2:28;2951:56759;;;-1:-1:-1;;;2951:56759:28;;;;;51820:45;;2951:56759;51820:45;;2951:56759;-1:-1:-1;;;2951:56759:28;;;;;;;;1744:340:19;;;;45161:974:28;45639:28;;;;;;;45630:38;45639:28;;;;:::i;:::-;45630:38;;:::i;:::-;45717:48;-1:-1:-1;;;;;45717:48:28;;;:::i;:::-;2951:56759;;4373:4;2951:56759;;;;;;4373:4;2951:56759;;;;;;;;45800:68;51726:27;2951:56759;;;-1:-1:-1;;;;;45822:46:28;2951:56759;;;;;;-1:-1:-1;;;;;51763:38:28;2951:56759;;;;;;45822:46;;:::i;:::-;2951:56759;45800:68;;:::i;:::-;45887:6;;45883:242;;45161:974;;;;;2951:56759;45161:974;;-1:-1:-1;;;;;;;;;;;45161:974:28;;;45883:242;-1:-1:-1;;;;;;;;;;;45935:20:28;;;;2951:56759;45935:20;;46085:25;45994:45;45935:20;;;46072:38;45935:20;;:::i;:::-;45994:45;:::i;:::-;46085:25;;:::i;:::-;46072:38;;:::i;:::-;45883:242;;;;;;;;2951:56759;-1:-1:-1;;;2951:56759:28;;;;;;;;50399:42;;;;;;;2951:56759;50399:42;2951:56759;50399:42;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;;;2951:56759;;4304:2;2951:56759;;4304:2;;;;50280:371;2951:56759;4373:4;;2951:56759;;;-1:-1:-1;;;50596:40:28;;-1:-1:-1;;;;;2951:56759:28;;;50596:40;;;2951:56759;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;50596:40;;;;;;;-1:-1:-1;;50596:40:28;;;50280:371;50564:72;;50280:371;;;50596:40;;;;;;;2951:56759;50596:40;2951:56759;50596:40;;;;;;;:::i;:::-;;;;;;;;2951:56759;;4304:2;2951:56759;;4304:2;;;;50255:1171;50935:379;;;;-1:-1:-1;51054:7:28;4373:4;2951:56759;;;-1:-1:-1;;;51054:46:28;;-1:-1:-1;;;;;2951:56759:28;51076:12;;2951:56759;;;51054:46;;2951:56759;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;51054:46;;;;;;;-1:-1:-1;;51054:46:28;;;50935:379;51010:90;51119:30;51167:17;;50935:379;;51340:28;;;;:::i;:::-;51394:21;;;;;:::i;:::-;50255:1171;;;51054:46;;;;;;;2951:56759;51054:46;2951:56759;51054:46;;;;;;;:::i;:::-;;;;;;;50935:379;51255:7;4373:4;2951:56759;;;-1:-1:-1;;;51255:44:28;;-1:-1:-1;;;;;2951:56759:28;51275:12;;2951:56759;;;51255:44;;2951:56759;;;;;;;;;;;;;;51275:12;2951:56759;;;;;;-1:-1:-1;;;;;2951:56759:28;51255:44;;;;;;;-1:-1:-1;;51255:44:28;;;50935:379;51223:76;;50935:379;;;51255:44;;;;;;;2951:56759;51255:44;2951:56759;51255:44;;;;;;;:::i;:::-;;;;;;;2951:56759;-1:-1:-1;;;2951:56759:28;;;;;;;;;-1:-1:-1;;;2951:56759:28;;;;;;;;;-1:-1:-1;;;2951:56759:28;;;;;1243:20:21;1252:11;1257:6;1252:11;;;1243:20;;34662:123:28;2951:56759;;;;;34662:123;;2951:56759;-1:-1:-1;;;2951:56759:28;;;;;49931:49;;2951:56759;49931:49;;5096:79;-1:-1:-1;;;5148:16:28;;2951:56759;5148:16;;2951:56759;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;2281:72:5;;;:::i;:::-;-1:-1:-1;;;;;2951:56759:28;;30189:18;;;;;30185:377;;;;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;30576:18;;;;30572:377;;;;2951:56759;3217:103:6;;;;-1:-1:-1;;;;;;;;;;;3217:103:6;29156:53:28;3217:103:6;;;;;:::i;:::-;2281:72:5;;:::i;:::-;28310:37:28;28357;;28405:180;;;2951:56759;28595:180;;;2951:56759;28826:29;;28822:155;;2951:56759;28990:29;;28986:155;;-1:-1:-1;2951:56759:28;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;29166:10;;2951:56759;;;;;;;28986:155;29068:7;2951:56759;29104:25;;2951:56759;29097:4;;29077:10;;-1:-1:-1;;;;;2951:56759:28;29104:25;:::i;28822:155::-;28904:7;2951:56759;28940:25;;2951:56759;28933:4;;28913:10;;-1:-1:-1;;;;;2951:56759:28;28940:25;:::i;:::-;28822:155;;;28595:180;49151:30;28641:10;;;;2951:56759;;28633:7;2951:56759;;;;;;28633:27;-1:-1:-1;;;;;28633:45:28;2951:56759;;;;;28633:45;:::i;:::-;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;49151:30;;:::i;:::-;28595:180;;;;28405;48658:30;28451:10;;;;2951:56759;;28443:7;2951:56759;;28443:45;2951:56759;;;28443:45;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;28443:45;:::i;:::-;;;:::i;:::-;2951:56759;;48658:30;;:::i;:::-;28405:180;;;;30572:377;2951:56759;;;;;30661:7;2951:56759;;;30786:39;2951:56759;;30786:39;;:::i;:::-;30688:239;;;;;;;2951:56759;;;;;;4304:2;;;;;;;;;;30688:239;;2951:56759;;;;;30763:4;;30727:10;2951:56759;30688:239;;;:::i;:::-;;;;;;;30572:377;;;;30688:239;;;;;;;;;;:::i;:::-;2951:56759;;30688:239;;;;;;;30185:377;2951:56759;;;;;30274:7;2951:56759;;;30399:39;2951:56759;;30399:39;;:::i;:::-;30301:239;;;;;;;2951:56759;;;;;;;;4304:2;;;;;;;;;;30301:239;;2951:56759;;;;;30376:4;;30340:10;2951:56759;30301:239;;;:::i;:::-;;;;;;30185:377;30301:239;;;;;:::i;:::-;2951:56759;;30301:239;;30185:377;;2951:56759;;;;;;;;;;;;;;;;10756:22;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;10800:7;2951:56759;;;10830:7;2951:56759;;;;;;;4373:4;2951:56759;;10952:7;4373:4;2951:56759;11009:32;2951:56759;;;11137:18;2951:56759;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2281:72:5;;:::i;:::-;33267:79:28;;:::i;:::-;2951:56759;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4886:19:28;2951:56759;;;;;;;;;;;-1:-1:-1;2951:56759:28;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;:::i;:::-;;;;5100:15;:25;5096:79;;2281:72:5;;:::i;:::-;19844:32:28;19796:20;;;;:::i;:::-;19844:32;:::i;:::-;19887:22;-1:-1:-1;;;;;;;;;;19956:60:28;:32;2951:56759;;;;;;;;;19956:60;:::i;:::-;2951:56759;;20026:665;;;;2951:56759;;4373:4;2951:56759;;4373:4;2951:56759;;;;1744:340:19;;;4373:4:28;1744:340:19;;;;;;;2951:56759:28;20084:121;2951:56759;1744:340:19;4373:4:28;-1:-1:-1;;;;;1744:340:19;;;20084:121:28;:::i;:::-;20240:7;4373:4;2951:56759;;-1:-1:-1;;;20240:110:28;;2951:56759;;;;;20240:110;;2951:56759;-1:-1:-1;;;;;2951:56759:28;4373:4;;2951:56759;;;;;4373:4;;2951:56759;;;;;-1:-1:-1;;;;;2951:56759:28;20240:110;;;;;;;;;;3282:1:6;20240:110:28;;;;;;20026:665;20219:131;20026:665;;2951:56759;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;3217:103:6;;:::i;:::-;3282:1;:::i;:::-;4304:2:28;2951:56759;-1:-1:-1;;;;;;;;;;;4304:2:28;2951:56759;-1:-1:-1;;;;;2951:56759:28;20980:22;;2951:56759;;21029:21;21162:5;-1:-1:-1;;;;;2951:56759:28;21029:21;2951:56759;21029:21;;2951:56759;;21077:21;;2951:56759;;21162:5;;;:::i;:::-;2951:56759;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;20240:110;;;;2951:56759;20240:110;2951:56759;20240:110;;;;;;;:::i;:::-;;;;;1744:340:19;;;;2951:56759:28;-1:-1:-1;;;2951:56759:28;;;;;;;;20026:665;2951:56759;4373:4;;;;;;;;;1744:340:19;;;4373:4:28;1744:340:19;;;;;;;2951:56759:28;20414:121;2951:56759;1744:340:19;4373:4:28;-1:-1:-1;;;;;1744:340:19;;;20414:121:28;:::i;:::-;2951:56759;;;;;;;4373:4;2951:56759;-1:-1:-1;;;;;2951:56759:28;;4304:2;;;;;;;;20570:110;;2951:56759;;20570:110;;2951:56759;4373:4;2951:56759;4373:4;;2951:56759;;;4373:4;;2951:56759;20570:110;;;;;;;;;;3282:1:6;20570:110:28;;;;;;20026:665;20549:131;20026:665;;;20570:110;;;;2951:56759;20570:110;2951:56759;20570:110;;;;;;;:::i;:::-;;;;;5096:79;-1:-1:-1;;;5148:16:28;;2951:56759;5148:16;;2951:56759;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;;;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;;;;:::i;:::-;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;3217:103:6;;:::i;:::-;-1:-1:-1;;;;;;;;;;;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;13030:10;:27;2951:56759;;13149:4;13022:56;;;:::i;:::-;13123:30;4304:2;;13196:46;4304:2;;-1:-1:-1;;;;4304:2:28;;;;;;-1:-1:-1;;;4304:2:28;;;;;;;;13275:18;2951:56759;4304:2;;13467:23;;-1:-1:-1;;;;;2951:56759:28;;;;;;13320:27;;13316:108;;2951:56759;13467:23;;:::i;13316:108::-;2951:56759;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;13368:45;;;13316:108;;;4304:2;-1:-1:-1;;;4304:2:28;;2951:56759;4304:2;;2951:56759;-1:-1:-1;;;2951:56759:28;;;;;;;;;;;;;;;;;;4859:21;2951:56759;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;33482:10;:21;:45;;;;2951:56759;;;;2281:72:5;;:::i;:::-;3496:4;2951:56759:28;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;3515:20:5;2951:56759:28;;;33482:10;2951:56759;;3515:20:5;2951:56759:28;;;-1:-1:-1;;;2951:56759:28;;;;;33482:45;-1:-1:-1;33521:6:28;2951:56759;-1:-1:-1;;;;;2951:56759:28;33482:10;33507:20;33482:45;;2951:56759;-1:-1:-1;2951:56759:28;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;5100:15;;:25;5096:79;;2281:72:5;;;;;;:::i;:::-;22576:67:28;;;;22604:7;2951:56759;-1:-1:-1;;;;;2951:56759:28;22576:67;-1:-1:-1;;;;;2951:56759:28;;22727:119;;;;2951:56759;;22747:42;;-1:-1:-1;;;;;2951:56759:28;22747:42;:::i;:::-;22727:119;;22861:64;;;;;;2951:56759;;;;;;4304:2;;;;;;;;;;22861:64;;2951:56759;;;;;22894:4;;22874:10;2951:56759;22861:64;;;:::i;:::-;;;;;;;22727:119;5096:79;2281:72:5;;;:::i;22861:64:28:-;;;;;:::i;:::-;2951:56759;;22861:64;;;;22727:119;2951:56759;;22804:42;;-1:-1:-1;;;;;2951:56759:28;22804:42;:::i;:::-;22727:119;;;22576:67;22635:7;2951:56759;-1:-1:-1;;;;;2951:56759:28;22576:67;;5096:79;-1:-1:-1;;;5148:16:28;;2951:56759;5148:16;;2951:56759;;;;;;;;;;;;;3217:103:6;;:::i;:::-;13566:121:28;;:::i;:::-;-1:-1:-1;;;;;;;;;;;2951:56759:28;966:10:4;-1:-1:-1;;;;;2951:56759:28;;;2869:24:0;2865:96;;2989:6;966:10:4;2989:6:0;:::i;2865:96::-;-1:-1:-1;;;2916:34:0;;966:10:4;2951:56759:28;;;;2916:34:0;2951:56759:28;-1:-1:-1;2951:56759:28;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;;;;:::i;:::-;;;:::i;:::-;;;;:::i;:::-;;;;:::i;:::-;;;;:::i;:::-;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;5100:15;;:25;5096:79;;2281:72:5;;:::i;:::-;17947:67:28;;;;17975:7;2951:56759;-1:-1:-1;;;;;2951:56759:28;17947:67;-1:-1:-1;;;;;2951:56759:28;;18098:119;;;;2951:56759;;18118:42;;-1:-1:-1;;;;;2951:56759:28;18118:42;:::i;:::-;18098:119;;18232:64;;;;;3282:1:6;2951:56759:28;;;18232:64;2951:56759;;;;;;4304:2;;;;;;;;;;18232:64;;2951:56759;;;;;18265:4;;18245:10;2951:56759;18232:64;;;:::i;:::-;;;;;;;18098:119;2951:56759;;;;;;;:::i;18232:64::-;;;;2951:56759;18232:64;;;:::i;:::-;2951:56759;;18232:64;;;;2951:56759;;;18098:119;2951:56759;;18175:42;;-1:-1:-1;;;;;2951:56759:28;18175:42;:::i;:::-;18098:119;;;17947:67;18006:7;2951:56759;-1:-1:-1;;;;;2951:56759:28;17947:67;;5096:79;5148:16;;;2951:56759;5148:16;2951:56759;;5148:16;2951:56759;;;;;;-1:-1:-1;;2951:56759:28;;;;-1:-1:-1;;;;;2951:56759:28;;:::i;:::-;;;;12207:7;2951:56759;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;12238:21;12234:95;;2951:56759;;;;;;;;;;;;;;;;;;;12234:95;2951:56759;;;12234:95;;2951:56759;;;;;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;-1:-1:-1;;;;;2951:56759:28;;4726:16:2;;:34;;;;2951:56759:28;4790:16:2;2951:56759:28;4790:16:2;:50;;;;2951:56759:28;4855:13:2;:30;;;;2951:56759:28;4851:91:2;;;2951:56759:28;;-1:-1:-1;;;;;2951:56759:28;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;;;;4301:16:2;4979:67;;2951:56759:28;6893:76:2;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;-1:-1:-1;;;;;2951:56759:28;;2076:26:1;2072:95;;2195:12;;;:::i;:::-;6893:76:2;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;2951:56759:28;-1:-1:-1;;;;;;;;;;;4304:2:28;6893:76:2;;:::i;:::-;;;:::i;:::-;-1:-1:-1;;;;;;;;;;;2951:56759:28;;-1:-1:-1;;2951:56759:28;;;-1:-1:-1;;;;;2951:56759:28;;7278:27;;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;7348:28;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;7419:28;2951:56759;;7483:47;4304:2;;-1:-1:-1;;;;4304:2:28;-1:-1:-1;;;4304:2:28;;;7540:23;2951:56759;;-1:-1:-1;;2951:56759:28;;;;;-1:-1:-1;4304:2:28;;;2951:56759;;-1:-1:-1;4304:2:28;7675:32;2951:56759;;-1:-1:-1;;;;;;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;;;;;;7717:32;2951:56759;;;;;4304:2;;-1:-1:-1;;;4304:2:28;-1:-1:-1;;;;;;4304:2:28;;;2951:56759;;;;4304:2;;;;;;;;2951:56759;;;4304:2;;-1:-1:-1;;;4304:2:28;;;;2951:56759;;-1:-1:-1;;;7948:38:28;;7980:4;2951:56759;7948:38;;2951:56759;;;;;;;;;;7948:38;;;;;;;;2951:56759;7948:38;2951:56759;7948:38;;;;;2951:56759;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;4304:2;;;;;;;8066:38;;7980:4;2951:56759;8066:38;;2951:56759;8066:38;;;;;;8217:23;8066:38;2951:56759;8066:38;;;2951:56759;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;8114:33;2951:56759;;;8114:33;2951:56759;;;;;;;-1:-1:-1;;;;;2951:56759:28;;7483:47;2951:56759;;;7483:47;2951:56759;8217:23;:::i;:::-;8340:4;-1:-1:-1;;;;;2951:56759:28;;8314:30;;:91;;;2951:56759;8314:149;;;2951:56759;8314:203;;;2951:56759;8314:291;;;2951:56759;4304:2;;;2951:56759;4304:2;2951:56759;4304:2;8114:33;4304:2;;-1:-1:-1;;;;;4304:2:28;;;2951:56759;4304:2;;;-1:-1:-1;;;;;4304:2:28;;;;;8114:33;4304:2;-1:-1:-1;;;;;8726:68:28;2951:56759;;;;;;;;;;;4304:2;-1:-1:-1;;;;;4304:2:28;;;;2951:56759;;;;4304:2;;8726:68;4304:2;2951:56759;8941:20;4304:2;2951:56759;;;4301:16:2;5066:101;;2951:56759:28;5066:101:2;2951:56759:28;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;-1:-1:-1;;;;;;;;;;;2951:56759:28;5142:14:2;2951:56759:28;;;;;;5142:14:2;2951:56759:28;4304:2;;;;2951:56759;4304:2;2951:56759;;4304:2;8314:291;2951:56759;-1:-1:-1;;;;;2951:56759:28;;8534:31;:70;8314:291;8534:70;2951:56759;-1:-1:-1;;;;;2951:56759:28;;8569:35;8314:291;;:203;2951:56759;8271:4;-1:-1:-1;;;;;2951:56759:28;;8479:38;;8314:203;;:149;2951:56759;8271:4;-1:-1:-1;;;;;2951:56759:28;;8421:42;;8314:149;;:91;2951:56759;8271:4;-1:-1:-1;;;;;2951:56759:28;;8360:45;;8314:91;;8066:38;;;;2951:56759;8066:38;2951:56759;8066:38;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;2951:56759;;4304:2;2951:56759;4304:2;;;;;7948:38;;;;;;;;;;;;;;:::i;:::-;;;;2951:56759;;;;;;;;;2072:95:1;2125:31;;;2951:56759:28;2125:31:1;2951:56759:28;;;;;2125:31:1;4979:67:2;-1:-1:-1;;2951:56759:28;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;4979:67:2;;4851:91;4908:23;;;2951:56759:28;4908:23:2;2951:56759:28;;4908:23:2;4855:30;4872:13;;;4855:30;;;4790:50;4818:4;4810:25;:30;;-1:-1:-1;4790:50:2;;4726:34;2951:56759:28;;;;4301:16:2;;-1:-1:-1;4726:34:2;;;2951:56759:28;;;;;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;-1:-1:-1;;;;;;;;;;;29156:53:28;2951:56759;;:::i;:::-;3217:103:6;;:::i;:::-;2281:72:5;;:::i;:::-;2951:56759:28;;-1:-1:-1;;;;;2951:56759:28;;;28405:180;;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;28599:18;28595:180;;2951:56759;28826:29;;28822:155;;2951:56759;28990:29;;28986:155;;-1:-1:-1;2951:56759:28;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;29166:10;;2951:56759;;;;;;;29156:53;;;;1805:1:6;-1:-1:-1;;;;;;;;;;;4304:2:28;2951:56759;28986:155;29068:7;2951:56759;29104:25;;2951:56759;29097:4;;29077:10;;-1:-1:-1;;;;;2951:56759:28;29104:25;:::i;:::-;28986:155;;;28822;28904:7;2951:56759;28940:25;;2951:56759;28933:4;;28913:10;;-1:-1:-1;;;;;2951:56759:28;28940:25;:::i;:::-;28822:155;;;28595:180;49151:30;28641:10;;;;2951:56759;;28633:7;2951:56759;;28633:27;2951:56759;;;28633:27;-1:-1:-1;;;;;28633:45:28;2951:56759;;;;;28633:45;:::i;49151:30::-;28595:180;;;;28405;48658:30;28451:10;;;2951:56759;;28443:7;2951:56759;;28443:45;2951:56759;;;28443:45;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;28443:45;:::i;:::-;2951:56759;;48658:30;;:::i;:::-;28405:180;;;2951:56759;;;;;;-1:-1:-1;;2951:56759:28;;;;2303:62:1;;:::i;:::-;-1:-1:-1;;;;;;;;;;;2951:56759:28;;-1:-1:-1;;;;;;2951:56759:28;;;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;;;;;-1:-1:-1;;;;;;;2951:56759:28;3975:40:1;-1:-1:-1;;3975:40:1;2951:56759:28;;;;;;;-1:-1:-1;;2951:56759:28;;;;33141:16;2951:56759;-1:-1:-1;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;;;;;;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;3217:103:6;;:::i;:::-;2281:72:5;;:::i;:::-;13905:32:28;13926:10;13905:32;:::i;:::-;;13926:10;2951:56759;;13947:7;2951:56759;;13947:29;2951:56759;;;13947:29;2951:56759;;;;;;;;;;;;;;;;;;;;;;;;;;;14000:42;2951:56759;13926:10;14000:42;;13947:29;-1:-1:-1;;;;;;;;;;;4304:2:28;2951:56759;;;;;;;-1:-1:-1;;2951:56759:28;;;;5111:6:3;-1:-1:-1;;;;;2951:56759:28;5102:4:3;5094:23;5090:145;;2951:56759:28;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;5090:145:3;4865:29;;;2951:56759:28;5195:29:3;2951:56759:28;;5195:29:3;2951:56759:28;;;-1:-1:-1;;2951:56759:28;;;;;;:::i;:::-;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4688:6:3;2951:56759:28;4679:4:3;4671:23;;;:120;;;;2951:56759:28;4654:251:3;;;2303:62:1;;:::i;:::-;2951:56759:28;;-1:-1:-1;;;6151:52:3;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;6151:52:3;;2951:56759:28;;6151:52:3;;;2951:56759:28;-1:-1:-1;6147:437:3;;2320:47:9;;;;2951:56759:28;6513:60:3;2951:56759:28;;;;6513:60:3;6147:437;6245:40;-1:-1:-1;;;;;;;;;;;6245:40:3;;;6241:120;;2263:29:9;;;:34;2259:119;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;-1:-1:-1;;;;;;2951:56759:28;;;;;2922:27:9;-1:-1:-1;;2922:27:9;2951:56759:28;;2964:15:9;:11;;2951:56759:28;4255:25:14;;4297:55;4255:25;;;;;;;;:::i;:::-;4297:55;;:::i;:::-;2951:56759:28;2960:148:9;6648:9;;;;6644:70;;2951:56759:28;6644:70:9;6684:19;;;2951:56759:28;6684:19:9;2951:56759:28;;6684:19:9;2259:119;2320:47;;;2951:56759:28;2320:47:9;2951:56759:28;;;;2320:47:9;6241:120:3;6312:34;;;2951:56759:28;6312:34:3;2951:56759:28;;;;6312:34:3;6151:52;;;;2951:56759:28;6151:52:3;;2951:56759:28;6151:52:3;;;;;;2951:56759:28;6151:52:3;;;:::i;:::-;;;2951:56759:28;;;;;6151:52:3;;;;;;;-1:-1:-1;6151:52:3;;4671:120;-1:-1:-1;;;;;;;;;;;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;4749:42:3;;;-1:-1:-1;4671:120:3;;;2951:56759:28;;;;;;-1:-1:-1;;2951:56759:28;;;;;25706:15;2951:56759;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;:::i;:::-;;;;:::i;:::-;;;;25706:15;;:::i;:::-;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;2303:62:1;;:::i;:::-;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;;3167:9:5;3163:62;;2951:56759:28;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;3823:22:5;2951:56759:28;;;966:10:4;2951:56759:28;;3823:22:5;2951:56759:28;3163:62:5;3199:15;;;2951:56759:28;3199:15:5;2951:56759:28;;3199:15:5;2951:56759:28;;;;;;-1:-1:-1;;2951:56759:28;;;;2357:1:1;2951:56759:28;;:::i;:::-;2303:62:1;;:::i;:::-;2357:1;:::i;2951:56759:28:-;;;;;;-1:-1:-1;;2951:56759:28;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;;;5100:15;:25;5096:79;;3217:103:6;;:::i;:::-;2281:72:5;;:::i;:::-;2951:56759:28;;;;24532:36;2951:56759;;;;;;24648:3;2951:56759;;24626:20;;;;;-1:-1:-1;;;;;24696:12:28;;;;:::i;:::-;2951:56759;;24710:12;;;;;:::i;:::-;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;49886:27;;;;:::i;:::-;2951:56759;;;;49931:7;2951:56759;;;;;;;49931:24;2951:56759;;;;49931:49;;;;24648:3;2951:56759;;;;34551:22;;;34550:31;;2951:56759;;;;34550:31;34662:123;;24648:3;1216:7:21;1212:11;;;1181:2;2951:56759:28;;;1243:5:21;;;;:20;;24648:3:28;2951:56759;;;;;;;;-1:-1:-1;;;;;2951:56759:28;49931:7;2951:56759;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;50255:1171;;;;50280:371;;;;-1:-1:-1;2951:56759:28;4373:4;;2951:56759;;;-1:-1:-1;;;50399:42:28;;-1:-1:-1;;;;;2951:56759:28;;;50399:42;;;2951:56759;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;2951:56759:28;50399:42;;;;;;2951:56759;;;50399:42;;;50280:371;50355:86;50460:30;50508:17;2951:56759;50280:371;;50702:38;50703:28;;;;;:::i;50702:38::-;50769:48;50883:21;50769:48;;;:::i;:::-;50832:25;50883:21;;:::i;:::-;50255:1171;;45165:25;2951:56759;;;;;-1:-1:-1;;;;;2951:56759:28;;;;45165:29;;2951:56759;;45244:28;;;-1:-1:-1;;;;;45244:28:28;;;45235:38;45244:28;;:::i;45235:38::-;2951:56759;1744:340:19;;;;;;;;;;4373:4:28;1744:340:19;;;;;45393:26:28;4373:4;45454:42;1744:340:19;;;;45393:26:28;:::i;:::-;45454:42;;:::i;:::-;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;4373:4;2951:56759;;;;;;4373:4;2951:56759;;;;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;51726:27;45454:63;-1:-1:-1;;;;;45454:63:28;;;51763:38;45454:63;;:::i;:::-;45161:974;;2951:56759;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51620:96;51726:27;:::i;:::-;2951:56759;51763:38;2951:56759;51763:38;:::i;:::-;;4304:2;2951:56759;51821:18;51820:45;;;;45161:974;2951:56759;;;;51912:72;;;;;:::i;:::-;2951:56759;24614:10;;2951:56759;;;;;;;;;51820:45;51845:10;;;:19;51820:45;;45161:974;45639:28;;;;;;;;45630:38;45639:28;;;;:::i;:::-;45630:38;;:::i;:::-;45717:48;-1:-1:-1;;;;;45717:48:28;;;:::i;:::-;2951:56759;;4373:4;2951:56759;;;;;;4373:4;2951:56759;;;;;;;45800:68;51763:38;2951:56759;-1:-1:-1;;;;;45822:46:28;51726:27;2951:56759;;;-1:-1:-1;;;;;2951:56759:28;;;;45822:46;;:::i;45800:68::-;45887:6;;45883:242;;45161:974;;;;-1:-1:-1;;;;;;;;;;;45161:974:28;;2951:56759;45161:974;;;45883:242;2951:56759;45935:20;;;-1:-1:-1;;;;;;;;;;;45935:20:28;;46085:25;45994:45;45935:20;;;46072:38;45935:20;;:::i;46072:38::-;45883:242;;;;;;;50399:42;;;;;;;2951:56759;50399:42;;;;;;;;;:::i;:::-;;;;;;;50280:371;2951:56759;4373:4;;2951:56759;;;-1:-1:-1;;;50596:40:28;;-1:-1:-1;;;;;2951:56759:28;;;50596:40;;;2951:56759;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;2951:56759:28;50596:40;;;;;;2951:56759;;;50596:40;;;50280:371;50564:72;;50280:371;;;50596:40;;;;;;;2951:56759;50596:40;;;;;;;;;:::i;:::-;;;;;;;50255:1171;50935:379;;;;-1:-1:-1;2951:56759:28;4373:4;2951:56759;;;-1:-1:-1;;;51054:46:28;;-1:-1:-1;;;;;2951:56759:28;51076:12;;2951:56759;;;51054:46;;2951:56759;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;51054:46;;;;;;;;2951:56759;;;51054:46;;;50935:379;51010:90;51119:30;51167:17;2951:56759;50935:379;;51340:28;;;;:::i;:::-;51394:21;;;;;:::i;:::-;50255:1171;;;51054:46;;;;;;;2951:56759;51054:46;;;;;;;;;:::i;:::-;;;;;;;50935:379;2951:56759;4373:4;2951:56759;;;-1:-1:-1;;;51255:44:28;;-1:-1:-1;;;;;2951:56759:28;51275:12;;2951:56759;;;51255:44;;2951:56759;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;51255:44;;;;;;;;2951:56759;;;51255:44;;;50935:379;51223:76;;50935:379;;;51255:44;;;;;;;2951:56759;51255:44;;;;;;;;;:::i;:::-;;;;;;;2951:56759;;;;;;;;;1243:20:21;1252:11;1257:6;1252:11;;;1243:20;;34662:123:28;2951:56759;;;;;34662:123;;2951:56759;;;;;;;;;49931:49;49960:10;;;:19;49931:49;;24626:20;2951:56759;-1:-1:-1;;;;;;;;;;;4304:2:28;2951:56759;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;2951:56759:28;;;;4809:43;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;:::o;:::-;;;;-1:-1:-1;2951:56759:28;;;;;-1:-1:-1;2951:56759:28;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;:::o;:::-;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;;;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;:::o;:::-;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;:::o;:::-;-1:-1:-1;;;;;2951:56759:28;;;;;;-1:-1:-1;;2951:56759:28;;;;:::o;:::-;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;33865:200;33937:6;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;;;33937:17;;;33933:54;;2951:56759;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;34002:30;;2951:56759;34002:30;-1:-1:-1;;;;;;2951:56759:28;;33937:6;2951:56759;33865:200::o;33933:54::-;33970:7;;;;:::o;2281:72:5:-;;;;;;;;;:::i;:::-;2951:56759:28;;25752:3;-1:-1:-1;;;;;2951:56759:28;;25737:18;25733:106;;2281:72:5;-1:-1:-1;;;;;2951:56759:28;;25848:372;;2281:72:5;2345:1;;;;;;;2281:72;:::o;25848:372:28:-;25752:3;25898:26;;;;;;;;;;25897:35;5100:15;;:25;5096:79;;16011:5;2281:72:5;3282:1:6;2281:72:5;;;:::i;:::-;2951:56759:28;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;3217:103:6;;:::i;:::-;3282:1;:::i;:::-;4304:2:28;25752:3;-1:-1:-1;;;;;;;;;;;4304:2:28;-1:-1:-1;;;;;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;;;15829:22;;2951:56759;;16011:5;:::i;:::-;25848:372;;;;;;;;;25733:106;5100:15;;:25;5096:79;;3217:103:6;;:::i;:::-;2281:72:5;;:::i;:::-;25796:5:28;49886:27;23822:10;49886:27;:::i;:::-;23822:10;25796:5;2951:56759;;;49931:7;2951:56759;;;;;;49931:24;2951:56759;;;;;49931:49;;;;25733:106;2951:56759;;;49931:24;34551:22;;;34550:31;2951:56759;;;;;;34662:123;;;25733:106;1216:7:21;1212:11;;;1181:2;2951:56759:28;;;1243:5:21;;;;:20;;25733:106:28;2951:56759;;;;;;;;-1:-1:-1;;;;;2951:56759:28;49931:7;2951:56759;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;25796:5;50255:1171;;;;50280:371;;;;-1:-1:-1;50399:7:28;4373:4;;2951:56759;;;-1:-1:-1;;;50399:42:28;;-1:-1:-1;;;;;2951:56759:28;;;50399:42;;;2951:56759;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;50399:42;;;;;;;;;;;;50280:371;50355:86;50460:30;50508:17;;50280:371;;50702:38;50703:28;;;;;:::i;50702:38::-;50769:48;50883:21;50769:48;;;:::i;:::-;50832:25;50883:21;;:::i;:::-;50255:1171;;45165:25;2951:56759;;;;;-1:-1:-1;;;;;2951:56759:28;;;45101:20;;45165:29;;2951:56759;;45244:28;;;-1:-1:-1;;;;;45244:28:28;;;45235:38;45244:28;;:::i;45235:38::-;2951:56759;1744:340:19;;;;;;;;;;4373:4:28;1744:340:19;;;;;45393:26:28;4373:4;45454:42;1744:340:19;;;;45393:26:28;:::i;45454:42::-;-1:-1:-1;;;;;2951:56759:28;;;4373:4;2951:56759;;;;;;4373:4;2951:56759;;;;;;;45454:63;51763:38;45454:63;-1:-1:-1;;;;;;;;;;;2951:56759:28;45454:63;-1:-1:-1;;;;;45454:63:28;51726:27;45454:63;;;;;:::i;:::-;45161:974;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51620:96;51726:27;:::i;:::-;2951:56759;51763:38;2951:56759;51763:38;:::i;:::-;;4304:2;2951:56759;51821:18;51820:45;;;;;45161:974;2951:56759;;;;23822:10;;51912:72;23822:10;;;51912:72;:::i;:::-;25752:3;-1:-1:-1;;;;;;;;;;;4304:2:28;25733:106;;2951:56759;-1:-1:-1;;;2951:56759:28;;;;;51820:45;51845:10;;;:19;51820:45;;;2951:56759;-1:-1:-1;;;2951:56759:28;;;;;;;;45161:974;45639:28;;;;;;;45630:38;45639:28;;;;:::i;45630:38::-;45717:48;-1:-1:-1;;;;;45717:48:28;;;:::i;:::-;2951:56759;;4373:4;2951:56759;;;;;;4373:4;2951:56759;;;;;;;;;;45800:68;51726:27;2951:56759;;-1:-1:-1;;;;;45822:46:28;2951:56759;;;;;-1:-1:-1;;;;;51763:38:28;2951:56759;;;;;45822:46;;:::i;45800:68::-;45887:6;;45883:242;;45161:974;;;;-1:-1:-1;;;;;;;;;;;45161:974:28;;2951:56759;45161:974;;;45883:242;2951:56759;45935:20;;;-1:-1:-1;;;;;;;;;;;45935:20:28;;46085:25;45994:45;45935:20;;;46072:38;45935:20;;:::i;46072:38::-;45883:242;;;;;;;2951:56759;-1:-1:-1;;;2951:56759:28;;;;;;;;50399:42;;;;;;;2951:56759;50399:42;2951:56759;50399:42;;;;;;;:::i;:::-;;;;;;;;2951:56759;;4304:2;2951:56759;;4304:2;;;;50280:371;50596:7;4373:4;;2951:56759;;;-1:-1:-1;;;50596:40:28;;-1:-1:-1;;;;;2951:56759:28;;;50596:40;;;2951:56759;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;2951:56759:28;50596:40;;;;;;50280:371;;;50596:40;;;50280:371;50564:72;;50280:371;;50596:40;;;;;;;2951:56759;50596:40;2951:56759;50596:40;;;;;;;:::i;:::-;;;;;;;50255:1171;51255:7;4373:4;2951:56759;;;-1:-1:-1;;;51255:44:28;;-1:-1:-1;;;;;2951:56759:28;51275:12;;2951:56759;;51255:44;;;2951:56759;;;;;;;;50935:379;;-1:-1:-1;2951:56759:28;;25796:5;;50935:379;;;;;2951:56759;;;-1:-1:-1;;;;;2951:56759:28;;25796:5;2951:56759;;;;51255:44;;;;;;;;;50935:379;;;51255:44;;;50255:1171;51223:76;;;51394:21;51223:76;51340:28;51223:76;;51340:28;:::i;:::-;51394:21;;:::i;:::-;50255:1171;;;51255:44;;;;;;;2951:56759;51255:44;2951:56759;51255:44;;;;;;;:::i;:::-;;;;;;1243:20:21;1252:11;1257:6;1252:11;;;1243:20;;34662:123:28;2951:56759;;;;;34662:123;;49931:49;49960:10;;;:19;49931:49;;2951:56759;;;;;;;;;;:::o;:::-;;-1:-1:-1;;;;;2951:56759:28;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;:::o;:::-;;-1:-1:-1;;;;;;;2951:56759:28;;;;;;;-1:-1:-1;;;;;;;2951:56759:28;;;;;:::o;4304:2::-;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;4304:2;:::o;2951:56759::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;-1:-1:-1;;;;;2951:56759:28;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;:::o;4373:4::-;;;;;;;;;;:::o;:::-;;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;;4373:4::o;:::-;;;;;;;;;;;;;;;:::i;:::-;;;;:::i;:::-;;:::o;3326:384:6:-;1847:1;-1:-1:-1;;;;;;;;;;;2951:56759:28;3526:20:6;3522:88;;1847:1;-1:-1:-1;;;;;;;;;;;4304:2:28;3326:384:6:o;3522:88::-;3569:30;;;-1:-1:-1;3569:30:6;;-1:-1:-1;3569:30:6;2905:128:5;2951:56759:28;-1:-1:-1;;;;;;;;;;;2951:56759:28;;2966:61:5;;2905:128::o;2966:61::-;3001:15;;;-1:-1:-1;3001:15:5;;-1:-1:-1;3001:15:5;2951:56759:28;;-1:-1:-1;;;;;2951:56759:28;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;:::o;:::-;;-1:-1:-1;;;;;2951:56759:28;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;:::o;2658:162:1:-;-1:-1:-1;;;;;;;;;;;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;966:10:4;2717:23:1;2713:101;;2658:162::o;2713:101::-;2916:34:0;;;-1:-1:-1;2763:40:1;966:10:4;2763:40:1;2951:56759:28;;-1:-1:-1;2763:40:1;42373:402:28;-1:-1:-1;;;;;2951:56759:28;-1:-1:-1;2951:56759:28;;;42485:7;2951:56759;;;;;;-1:-1:-1;;;;;2951:56759:28;;;42532:14;;42528:241;;42373:402;:::o;42528:241::-;2951:56759;;42623:21;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;-1:-1:-1;;;;;2951:56759:28;;;;-1:-1:-1;;2951:56759:28;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;42623:21;2951:56759;-1:-1:-1;2951:56759:28;;;42485:7;2951:56759;;;;;;;;;;;;;;42718:33;;;;2951:56759;;-1:-1:-1;;;;2951:56759:28;-1:-1:-1;;;2951:56759:28;;;42373:402::o;2472:222:0:-;-1:-1:-1;;;;;;;;;;;2951:56759:28;;-1:-1:-1;;;;;;2951:56759:28;;;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;3975:40:1;-1:-1:-1;;3975:40:1;2472:222:0:o;58237:375:28:-;2951:56759;;-1:-1:-1;;;58378:30:28;;58402:4;58378:30;;;2951:56759;58237:375;;-1:-1:-1;;;;;2951:56759:28;;;58237:375;2951:56759;;58378:30;2951:56759;;58378:30;;;;;;;-1:-1:-1;58378:30:28;;;58237:375;2951:56759;58378:30;2951:56759;;;;1829:53:13;2951:56759:28;;;4304:2;;;;1829:53:13;;;;2951:56759:28;;;;;;1829:53:13;;;2951:56759:28;;;;;;;;;;;;;;;;;1829:53:13;;;;;;:::i;:::-;;:::i;:::-;2951:56759:28;;-1:-1:-1;;;58491:30:28;;58402:4;58378:30;58491;;2951:56759;;;;;;58491:30;;;;;;-1:-1:-1;58491:30:28;;;58237:375;58539:30;;;;:::i;:::-;:39;2951:56759;;58237:375::o;2951:56759::-;;;;-1:-1:-1;2951:56759:28;58378:30;-1:-1:-1;2951:56759:28;58491:30;;2951:56759;58491:30;;2951:56759;58491:30;;;;;;2951:56759;58491:30;;;:::i;:::-;;;2951:56759;;;;58539:30;2951:56759;;58491:30;;;;;-1:-1:-1;58491:30:28;;58378;;;;2951:56759;58378:30;;;;;2951:56759;58378:30;;;;;;2951:56759;58378:30;;;:::i;:::-;;;2951:56759;;;;;;58378:30;;2951:56759;58378:30;;;;;;-1:-1:-1;58378:30:28;;2951:56759;;;;;;;;;;;;;;;;;;:::o;40683:594::-;;40804:235;;40683:594;-1:-1:-1;;;;;2951:56759:28;41057:26;;2951:56759;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;41140:130;2951:56759;;;;;;;;41140:130;;;;2951:56759;-1:-1:-1;;;;;2951:56759:28;;41119:151;2951:56759;;;41119:151;2951:56759;41119:151;4304:2;;2951:56759;4304:2;;;;;;;2951:56759;4304:2;;;;;41119:151;4304:2;40683:594::o;40804:235::-;2951:56759;;-1:-1:-1;;;40903:57:28;;-1:-1:-1;;;40903:57:28;;;2951:56759;;;40903:57;2951:56759;-1:-1:-1;;;;;2951:56759:28;;40903:57;;;;;;;-1:-1:-1;40903:57:28;;;40804:235;40902:58;40804:235;40898:131;40987:27;;;-1:-1:-1;40987:27:28;40903:57;-1:-1:-1;40987:27:28;40903:57;;;;2951:56759;40903:57;2951:56759;40903:57;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;2951:56759;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;:::o;:::-;-1:-1:-1;;;;;2951:56759:28;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;:::o;35800:4641::-;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;36196:13;;;;:27;;35800:4641;2951:56759;;;36294:9;:14;:69;;;;35800:4641;2951:56759;;;36494:32;36446:20;;;;:::i;36494:32::-;-1:-1:-1;;37608:17:28;-1:-1:-1;;;;37889:421:28;;;;-1:-1:-1;;37954:7:28;4373:4;2951:56759;;;-1:-1:-1;;;37954:40:28;;2951:56759;;;;;-1:-1:-1;;;;;2951:56759:28;;;;-1:-1:-1;;2951:56759:28;;37954:40;;2951:56759;37954:40;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;37954:40:28;;;37889:421;37918:76;;;38061:26;37889:421;;-1:-1:-1;;;;;38419:30:28;38340:65;;;:::i;:::-;38419:30;;;:::i;:::-;2951:56759;;38468:19;;38464:126;;37889:421;-1:-1:-1;;;;;39793:28:28;38730:31;38604:32;;;;;;;;2951:56759;;38668:31;;;;;2951:56759;;;;38730:31;;;;2951:56759;-1:-1:-1;39793:28:28;:::i;:::-;2951:56759;;;;39793:46;2951:56759;;-1:-1:-1;;;;;40412:12:28;2951:56759;38668:31;2951:56759;;-1:-1:-1;2951:56759:28;;38604:32;2951:56759;;;;38668:31;2951:56759;;;-1:-1:-1;38730:31:28;2951:56759;;;-1:-1:-1;2951:56759:28;;;;;;;;;;;;;;;;20852:4;2951:56759;;;;-1:-1:-1;2951:56759:28;;;;;;39912:10;-1:-1:-1;;;;;;;;;;;2951:56759:28;39912:10;39887:313;;39912:10;40412:12;:::i;:::-;35800:4641::o;2951:56759::-;;;;-1:-1:-1;2951:56759:28;;-1:-1:-1;2951:56759:28;38464:126;2951:56759;;-1:-1:-1;;;38514:25:28;;;2951:56759;38514:25;2951:56759;38514:9;-1:-1:-1;;;;;2951:56759:28;38514:25;;;;;;;-1:-1:-1;38514:25:28;;;38464:126;2951:56759;38464:126;2951:56759;;;;-1:-1:-1;2951:56759:28;38514:25;-1:-1:-1;2951:56759:28;38514:25;;;;;;;;;;;;;;:::i;:::-;;;;37954:40;;;;;;;;2951:56759;37954:40;2951:56759;37954:40;;;;;;;:::i;:::-;;;;;;;;37889:421;2951:56759;;;;;;38162:40;2951:56759;;;;;;;;38162:7;4373:4;2951:56759;;-1:-1:-1;2951:56759:28;;4304:2;;;;;;;;;38162:40;;:7;:40;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;38162:40:28;;;37889:421;38126:76;;;38266:29;37889:421;;;38162:40;;;;;;;;2951:56759;38162:40;2951:56759;38162:40;;;;;;;:::i;:::-;;;;;;;;2951:56759;;;;-1:-1:-1;2951:56759:28;;-1:-1:-1;2951:56759:28;36294:69;2951:56759;36313:19;2951:56759;;;;;;36313:49;;;;36294:69;;;;36313:49;2951:56759;;;;;;;;;;;36337:24;36313:49;;;2951:56759;;;;-1:-1:-1;2951:56759:28;;-1:-1:-1;2951:56759:28;36196:27;2951:56759;-1:-1:-1;;;;;2951:56759:28;;36213:10;;36196:27;;35800:4641;;;;;;;;;:::i;:::-;;;;:::o;:::-;;;;;;;;;;;;;:::i;:::-;;;;:::o;59372:336::-;-1:-1:-1;;;;;2951:56759:28;59470:20;59466:45;;59525:18;2951:56759;;;;;;59525:89;;;59372:336;59521:181;;59372:336;;:::o;59521:181::-;-1:-1:-1;;;;;2951:56759:28;;59630:61;;;;;59489:1;2951:56759;59630:61;2951:56759;;;;40927:32;;;;;;;;59630:61;;2951:56759;;59630:61;;;2951:56759;59630:61;;;;;;;;59521:181;59372:336;:::o;59630:61::-;59489:1;59630:61;;;:::i;59525:89::-;-1:-1:-1;59570:10:28;-1:-1:-1;;;;;2951:56759:28;;59570:44;;59525:89;;2951:56759;;;;;;;:::o;:::-;;;;;;;;;;;;41375:744;41441:16;2951:56759;-1:-1:-1;;2951:56759:28;;;;;;;4373:4;2951:56759;;;4373:4;2951:56759;;;;;;;;;4373:4;2951:56759;;;;;;41478:36;;;:::i;:::-;41441:16;4304:2;41525:52;;49151:30;41965:22;2951:56759;;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;41730:23;963:19:19;-1:-1:-1;;;;;41670:21:28;2951:56759;;;;963:19:19;;:::i;:::-;41730:23:28;;;:::i;:::-;41767:20;41763:130;;41375:744;41965:22;;:::i;:::-;-1:-1:-1;;;;;41460:1:28;2951:56759;;;49151:30;:::i;:::-;42002:26;41998:115;;41375:744;;:::o;41998:115::-;42043:7;2951:56759;42079:22;;2951:56759;-1:-1:-1;;;;;2951:56759:28;42079:22;:::i;41763:130::-;41854:28;;;:::i;:::-;2951:56759;;;;;41811:18;2951:56759;;-1:-1:-1;2951:56759:28;41803:7;2951:56759;;-1:-1:-1;;;;;41803:79:28;41460:1;2951:56759;-1:-1:-1;2951:56759:28;41803:47;2951:56759;;;;;41803:79;:::i;:::-;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;;;41763:130;;;411:441:21;;-1:-1:-1;;;;;2951:56759:28;;488:5:21;;;:35;;;;411:441;2951:56759:28;;;;488:1:21;627:150;;-1:-1:-1;;;;;2951:56759:28;;634:20:21;589:6;634:20;;;;;2951:56759:28;-1:-1:-1;;;;;682:2:21;2951:56759:28;;;;;682:2:21;2951:56759:28;;;;;;;;;;;;627:150:21;;;2951:56759:28;;;;488:1:21;2951:56759:28;;488:1:21;2951:56759:28;634:20:21;2951:56759:28;634:20:21;;2951:56759:28;634:20:21;;;;2951:56759:28;4304:2;812::21;4304::28;2951:56759;798:29:21;411:441;:::o;2951:56759:28:-;;;;488:1:21;2951:56759:28;;488:1:21;2951:56759:28;488:35:21;502:21;497:26;;;;488:35;;;47027:408:28;2951:56759;47027:408;47421:1;47027:408;47131:258;;;;4304:2;;;;47131:258;4304:2;;2951:56759;47409:19;47027:408;:::o;47131:258::-;2951:56759;;;;;;4304:2;;2951:56759;47131:258;;9259:218:18;-1:-1:-1;;;;;9339:25:18;;9335:105;;-1:-1:-1;;;;;2951:56759:28;9259:218:18;:::o;9335:105::-;9387:42;;;;;9418:3;9387:42;2951:56759:28;;;;9387:42:18;;1303:160:13;2951:56759:28;;-1:-1:-1;;;1412:43:13;;;;-1:-1:-1;;;;;2951:56759:28;;;1412:43:13;;;2951:56759:28;;;;;;;;;1412:43:13;;;;;;;2951:56759:28;1412:43:13;:::i;44025:343:28:-;-1:-1:-1;;;;;44134:29:28;2951:56759;;;;44134:34;;;44130:72;;44324:37;2951:56759;-1:-1:-1;;;;;963:19:19;2951:56759:28;;963:19:19;:::i;:::-;44324:37:28;:::i;44130:72::-;44183:8;;2951:56759;44183:8;:::o;52504:5484::-;;;;2951:56759;52727:34;;2951:56759;52819:34;2951:56759;;52924:15;2951:56759;;;;;;;52924:67;;;;;;-1:-1:-1;52956:7:28;2951:56759;-1:-1:-1;;;;;2951:56759:28;;52924:67;53014:9;53010:748;;52924:67;-1:-1:-1;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;53802:24;;;;53975:263;;;;-1:-1:-1;;;;;2951:56759:28;48658:30;54014:70;2951:56759;;;48658:30;;:::i;:::-;54014:70;;:::i;:::-;53975:263;;2951:56759;;55105:24;;;;55276:260;;;2951:56759;49151:30;55315:69;2951:56759;49159:22;2951:56759;49151:30;;:::i;55315:69::-;55276:260;;52924:15;2951:56759;;;;;;56386:554;;55101:1247;56991:26;;;;;;56987:264;;55101:1247;57260:151;;;55101:1247;57424:26;57420:265;;55101:1247;57694:151;;;55101:1247;57886:21;;;57882:100;;52504:5484;;:::o;57882:100::-;57947:21;;-1:-1:-1;;;;;2951:56759:28;57927:44;;;;;2951:56759;;57927:44;2951:56759;;4304:2;;;;;;;57927:44;;;;;;;;;;52504:5484;;:::o;57927:44::-;;;;;;:::i;:::-;2951:56759;;52504:5484;:::o;57927:44::-;2951:56759;;4304:2;2951:56759;;4304:2;;;;57694:151;52924:15;2951:56759;57808:25;;57801:4;;-1:-1:-1;;;;;2951:56759:28;57808:25;:::i;:::-;57694:151;;;;57420:265;52924:15;2951:56759;;;;;;;;57470:39;;;57420:265;57466:209;;;57546:22;;;;:::i;:::-;57420:265;;;57466:209;57637:22;;-1:-1:-1;;;;;2951:56759:28;57637:22;:::i;:::-;57466:209;;57470:39;2951:56759;;;;;;57493:16;57470:39;;57260:151;57342:7;2951:56759;57374:25;;2951:56759;;57367:4;;;;-1:-1:-1;;;;;2951:56759:28;57374:25;:::i;:::-;57260:151;;56987:264;52924:15;2951:56759;;;;;;57037:38;;;;56987:264;-1:-1:-1;57033:208:28;;;57112:22;;;;:::i;:::-;56987:264;;;57033:208;57174:7;2951:56759;57203:22;;2951:56759;;;-1:-1:-1;;;;;2951:56759:28;57203:22;:::i;:::-;57033:208;;57037:38;2951:56759;;;;;;57037:38;;;56386:554;2951:56759;;;;;;;;56469:67;;56386:554;56465:172;;56386:554;56655:16;:68;;;56386:554;56651:173;;56386:554;56842:21;56838:92;56386:554;56838:92;2951:56759;;-1:-1:-1;;;;;;2951:56759:28;;;56883:32;;;;;2951:56759;;56883:32;2951:56759;;;;4304:2;;;;;;;;56883:32;;;;;2951:56759;56883:32;;;;;;;;56838:92;;;;56386:554;;56883:32;;;;;;2951:56759;56883:32;;:::i;:::-;2951:56759;56883:32;;;;;56651:173;56788:21;56763:46;56788:21;56763:46;;:::i;:::-;56651:173;;56655:68;56701:21;;56676:46;;56655:68;;56465:172;56601:21;;56576:46;56601:21;56576:46;;:::i;:::-;56465:172;;;56469:67;56514:21;;56489:46;;56469:67;;55276:260;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;;;;;;;;;;;;;55423:7;2951:56759;;55423:23;2951:56759;;;55423:23;-1:-1:-1;;;;;55423:40:28;2951:56759;;;;;55423:40;:::i;:::-;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;55486:35;55276:260;;55101:1247;;;;;;53975:263;2951:56759;-1:-1:-1;;;;;2951:56759:28;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;;;;;;;;;;54123:7;2951:56759;;54123:41;2951:56759;;;54123:41;2951:56759;;;;;;;54123:41;:::i;:::-;2951:56759;;;;;;;;;;54187:36;53975:263;;53798:1263;;;-1:-1:-1;;;;;53798:1263:28;;;53010:748;2951:56759;;;;-1:-1:-1;;;;;53308:24:28;53245:20;2951:56759;;48658:30;53100:48;53101:34;53014:9;;53101:34;:::i;53100:48::-;2951:56759;;;;48658:30;:::i;:::-;53245:20;;:::i;:::-;53014:9;;53308:24;:::i;:::-;53043:705;;53010:748;;;;53043:705;2951:56759;;;-1:-1:-1;;;;;53653:24:28;53590:20;53458:22;2951:56759;49151:30;53445:48;53446:34;53014:9;;53446:34;:::i;49151:30::-;53590:20;;:::i;:::-;53014:9;;53653:24;:::i;:::-;53043:705;;;52924:67;-1:-1:-1;;;;;2951:56759:28;;52924:67;;52504:5484;;;;;;52760:1;52727:34;52760:1;52771:37;52760:1;52819:34;52760:1;52863:37;52760:1;2951:56759;52924:15;2951:56759;;;;;;;52924:67;;;;;;-1:-1:-1;52956:7:28;2951:56759;-1:-1:-1;;;;;2951:56759:28;;52924:67;53014:9;53010:748;;52924:67;2951:56759;-1:-1:-1;;;;;2951:56759:28;;-1:-1:-1;;;;;2951:56759:28;;53802:24;;;53798:1263;53802:24;;;-1:-1:-1;;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;53975:263;;;;2951:56759;48658:30;54014:70;2951:56759;52760:1;2951:56759;48658:30;;:::i;54014:70::-;53975:263;;-1:-1:-1;;;;;2951:56759:28;;-1:-1:-1;;;;;2951:56759:28;;55105:24;;;55101:1247;55105:24;;;-1:-1:-1;;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;;55276:260;;;2951:56759;49151:30;55315:69;2951:56759;49159:22;2951:56759;49151:30;;:::i;55315:69::-;55276:260;;52924:15;2951:56759;;;;;;56386:554;;55101:1247;56991:26;;56987:264;;55101:1247;57264:29;;57260:151;;55101:1247;57424:26;;57420:265;;55101:1247;57698:29;;57694:151;;57886:21;;;57882:100;;52504:5484;;:::o;57694:151::-;52924:15;2951:56759;57808:25;;57801:4;;-1:-1:-1;;;;;2951:56759:28;57808:25;:::i;:::-;57694:151;;;;57420:265;52924:15;2951:56759;;;;;;;;57470:39;;;57420:265;57466:209;;;57546:22;;;;:::i;:::-;57420:265;;;57466:209;57637:22;;-1:-1:-1;;;;;2951:56759:28;57637:22;:::i;:::-;57466:209;;57470:39;2951:56759;;;;;;57493:16;57470:39;;57260:151;57342:7;2951:56759;57374:25;;2951:56759;57367:4;;;;-1:-1:-1;;;;;2951:56759:28;57374:25;:::i;:::-;57260:151;;;56987:264;52924:15;2951:56759;;;;;;57037:38;;;;56987:264;-1:-1:-1;57033:208:28;;;57112:22;;;;:::i;:::-;56987:264;;;57033:208;57174:7;2951:56759;57203:22;;2951:56759;;;-1:-1:-1;;;;;2951:56759:28;57203:22;:::i;:::-;57033:208;;57037:38;2951:56759;;;;;;57037:38;;;56386:554;52760:1;;2951:56759;;;;;;56469:67;;56386:554;56465:172;;56386:554;56655:16;:68;;;56386:554;56651:173;;56386:554;56842:21;56838:92;56386:554;56838:92;-1:-1:-1;;;;;2951:56759:28;;;56883:32;;;;;52760:1;2951:56759;56883:32;2951:56759;;;;4304:2;;;;;;;;56883:32;;;;;2951:56759;56883:32;;;;;;;56386:554;56883:32;;;;;52760:1;56883:32;;:::i;:::-;52760:1;56883:32;;56386:554;;56651:173;56788:21;56763:46;56788:21;56763:46;;:::i;:::-;56651:173;;56655:68;56701:21;;56676:46;;56655:68;;56465:172;56601:21;;56576:46;56601:21;56576:46;;:::i;:::-;56465:172;;;56469:67;56514:21;;56489:46;;56469:67;;55276:260;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;;;;;;;;;;;52760:1;2951:56759;55423:7;2951:56759;;55423:23;2951:56759;52760:1;2951:56759;55423:23;-1:-1:-1;;;;;55423:40:28;2951:56759;;;;;55423:40;:::i;:::-;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;52760:1;2951:56759;;;;;;55486:35;55276:260;;55101:1247;55556:24;;;;;;;;;55552:796;;55101:1247;;;;;55552:796;-1:-1:-1;;;;;2951:56759:28;;52760:1;2951:56759;;;55757:7;2951:56759;;;;;;55757:23;2951:56759;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;55798:33;;;2951:56759;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;52760:1;2951:56759;55757:7;2951:56759;;55757:23;2951:56759;52760:1;2951:56759;55883:23;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;52760:1;2951:56759;;;;;;55967:38;55794:544;55552:796;;;;55794:544;2951:56759;;;49151:30;-1:-1:-1;;;;;;;;;;;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;55757:23;2951:56759;;;;49151:30;:::i;:::-;2951:56759;;52760:1;2951:56759;55757:7;2951:56759;;55757:23;2951:56759;52760:1;2951:56759;56238:23;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;52760:1;2951:56759;;;;;;56288:35;55794:544;;53975:263;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;;;;;;;;;;;52760:1;2951:56759;54123:7;2951:56759;;54123:41;2951:56759;52760:1;2951:56759;54123:41;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;54123:41;:::i;:::-;2951:56759;;;;;52760:1;2951:56759;;;;54187:36;53975:263;;53798:1263;54258:24;;;;54254:807;;53798:1263;;;;;54254:807;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;52760:1;2951:56759;54462:7;2951:56759;;-1:-1:-1;;;;;2951:56759:28;52760:1;2951:56759;;;;;54503:35;;;;54499:552;2951:56759;;;;;-1:-1:-1;;;;;;;;;;;2951:56759:28;;52760:1;2951:56759;54462:7;2951:56759;;54590:44;2951:56759;52760:1;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;54590:44;;:::i;:::-;2951:56759;;;;;52760:1;2951:56759;;;;54675:39;54499:552;54254:807;;;;54499:552;2951:56759;;;48658:30;-1:-1:-1;;;;;;;;;;;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;52760:1;2951:56759;;;;48658:30;:::i;:::-;2951:56759;;52760:1;2951:56759;54462:7;2951:56759;;;52760:1;2951:56759;-1:-1:-1;;;;;;;2951:56759:28;;;;;;;;;;;52760:1;2951:56759;;;;55000:36;54499:552;;53010:748;53043:705;;;2951:56759;;;;53308:24;53245:20;52760:1;2951:56759;48658:30;53100:48;53101:34;53014:9;;53101:34;:::i;53100:48::-;2951:56759;-1:-1:-1;;;;;2951:56759:28;;48658:30;:::i;53308:24::-;53043:705;;53010:748;;;53043:705;2951:56759;;;53653:24;53590:20;53458:22;2951:56759;49151:30;53445:48;53446:34;53014:9;;53446:34;:::i;49151:30::-;53590:20;;:::i;:::-;53014:9;;53653:24;:::i;:::-;53043:705;;;52924:67;-1:-1:-1;;;;;2951:56759:28;;52924:67;;7084:141:2;2951:56759:28;-1:-1:-1;;;;;;;;;;;2951:56759:28;;;;7150:18:2;7146:73;;7084:141::o;7146:73::-;7191:17;;;-1:-1:-1;7191:17:2;;-1:-1:-1;7191:17:2;2951:56759:28;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;-1:-1:-1;2951:56759:28;;;;:::o;:::-;;;:::o;58892:166::-;58975:25;58892:166;;;;;58975:25;;;;:::i;:::-;;2951:56759;;;58892:166::o;2951:56759::-;;;;58975:25;2951:56759;;58975:25;2951:56759;42982:808;-1:-1:-1;;;;;2951:56759:28;43116:19;;43112:58;;43217:32;2951:56759;-1:-1:-1;;;;;2951:56759:28;;;;;-1:-1:-1;;;;;43217:60:28;2951:56759;;;;43217:60;:::i;:::-;2951:56759;43291:31;;43287:70;;963:19:19;;;;:::i;:::-;2951:56759:28;4373:4;2951:56759;;;;;;4373:4;2951:56759;;;;;;;43656:55;43590:51;-1:-1:-1;;;;;43537:104:28;:174;43590:51;;43739:44;43590:51;43503:218;43590:51;;:::i;:::-;43537:104;;:::i;:::-;2951:56759;;;;43656:55;;:::i;43537:174::-;43503:218;2951:56759;43503:218;:::i;:::-;;4304:2;43739:44;:::i;43287:70::-;43338:8;;;;2951:56759;43338:8;:::o;43112:58::-;43151:8;2951:56759;43151:8;:::o;4059:629:13:-;2847:1:14;4059:629:13;3510:55:14;4059:629:13;2951:56759:28;;;;;;3462:31:14;;;;;;;;;;;;:::i;:::-;3510:55;;;:::i;:::-;2951:56759:28;;4551:22:13;;;;:57;;;;4059:629;4547:135;;;;4059:629;:::o;4547:135::-;4631:40;;;2847:1:14;4631:40:13;;2951:56759:28;;2847:1:14;4631:40:13;4551:57;4578:30;;;3462:31:14;4578:30:13;;;;;;;;:::i;:::-;4577:31;4551:57;;;;2096:672:19;1744:340;;;2274:488;;;;;;4373:4:28;2274:488:19;;;;;4373:4:28;2274:488:19;;;;;;;;2096:672;:::o;4625:582:14:-;;4797:8;;-1:-1:-1;2951:56759:28;;5874:21:14;:17;;6046:142;;;;;;5870:383;6225:17;;;5894:1;6225:17;;5894:1;6225:17;4793:408;2951:56759:28;;5045:22:14;:49;;;4793:408;5041:119;;5173:17;;:::o;5041:119::-;-1:-1:-1;;;5066:1:14;5121:24;;;-1:-1:-1;;;;;2951:56759:28;;;;5121:24:14;2951:56759:28;;;5121:24:14;5045:49;5071:18;;;:23;5045:49;;35800:4641:28;;;;;;;;;;;25867:1;2951:56759;-1:-1:-1;;;;;2951:56759:28;;36196:13;;:27;;;35800:4641;2951:56759;;;36294:9;:14;:69;;;;;;;35800:4641;2951:56759;;;36446:20;;;;;:::i;:::-;36494:32;;;;;:::i;:::-;36537:1061;;;35800:4641;-1:-1:-1;;;37608:17:28;;;;37635;;;;37693:20;;;;-1:-1:-1;;;;;;;37795:22:28;37863:10;;37859:930;;35800:4641;38834:15;-1:-1:-1;38884:47:28;38900:26;;;;:::i;:::-;38941:19;-1:-1:-1;2951:56759:28;-1:-1:-1;;;;;2951:56759:28;;38970:805;;35800:4641;39793:28;-1:-1:-1;;;;;39793:28:28;;;;;:::i;:::-;2951:56759;;;;39793:46;2951:56759;;;;;-1:-1:-1;;;;;2951:56759:28;;;-1:-1:-1;;;;;2951:56759:28;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;37863:10;2951:56759;;;;;;;39912:10;;39887:313;2951:56759;-1:-1:-1;;;;;;;;;;;39887:313:28;;40412:12;;;;;;;;;;;;39912:10;40412:12;:::i;2951:56759::-;-1:-1:-1;;;2951:56759:28;;;;;38970:805;39019:32;;;;;;46575:5;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;;;;4304:2;;;;1744:340:19;;2951:56759:28;;;4304:2;;;;;;;;;;46575:5;4304:2;2951:56759;;;46652:9;2951:56759;;4304:2;;47902:250;;;;2951:56759;;4304:2;;;47967:67;47902:250;;36106:12;2951:56759;4304:2;;;2951:56759;48172:19;39105:10;39084:32;39105:10;39084:32;:::i;:::-;39152:22;-1:-1:-1;;;;;2951:56759:28;;39152:22;;:::i;:::-;;;39202:45;;;;:::i;:::-;39261:454;;;;;-1:-1:-1;39290:7:28;4373:4;-1:-1:-1;;;;;2951:56759:28;39290:66;;;;;;2951:56759;;;;;;;;;4304:2;;;;;;;;;;39290:66;;;;;:7;:66;;;:::i;:::-;;;;;;;;;;;;;;;39261:454;39375:30;;;;;:::i;:::-;39261:454;;-1:-1:-1;;;;;2951:56759:28;;;;;38970:805;;;39290:66;;;;;;;;:::i;:::-;2951:56759;;39290:66;;;;;;2951:56759;;4304:2;2951:56759;;4304:2;;;;39290:66;2951:56759;;;39261:454;39444:7;4373:4;2951:56759;;;;;-1:-1:-1;;;;;2951:56759:28;;39444:66;;;;;;2951:56759;;-1:-1:-1;2951:56759:28;;;;4304:2;;;;;;;;;;39444:66;;;;;;;;;:::i;:::-;;;;;;;;;;;39261:454;4304:2;2951:56759;4304:2;36106:12;4304:2;2951:56759;39675:25;39659:41;39675:25;;;;;:::i;:::-;39659:41;;;:::i;:::-;;;39261:454;;39444:66;;;;;-1:-1:-1;39444:66:28;;:::i;:::-;-1:-1:-1;;2951:56759:28;39444:66;;47902:250;4304:2;;;48092:48;47902:250;;;2951:56759;;;;-1:-1:-1;2951:56759:28;;-1:-1:-1;2951:56759:28;37859:930;37889:421;;;;;;;;;;;;2951:56759;;;37954:40;2951:56759;;;;;;37954:7;4373:4;2951:56759;;-1:-1:-1;2951:56759:28;;4304:2;;;;;;;;;37954:40;;;;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;37954:40:28;;;37889:421;37918:76;;;;38061:26;;;37889:421;38340:65;;;:::i;:::-;38419:30;;;;;;:::i;:::-;;;-1:-1:-1;;;;;2951:56759:28;;38468:19;38464:126;;37889:421;38604:32;;;;2951:56759;-1:-1:-1;;;;;2951:56759:28;;38668:31;;;;2951:56759;-1:-1:-1;;;;;2951:56759:28;;38730:31;;;;2951:56759;37859:930;;;38464:126;2951:56759;;-1:-1:-1;;;38514:25:28;;;2951:56759;38514:25;2951:56759;38514:9;-1:-1:-1;;;;;2951:56759:28;38514:25;;;;;;;-1:-1:-1;38514:25:28;;;38464:126;2951:56759;38464:126;2951:56759;;;;-1:-1:-1;2951:56759:28;38514:25;-1:-1:-1;2951:56759:28;38514:25;;;;;;;;;;;;;;:::i;:::-;;;;37954:40;;;;;;;2951:56759;37954:40;2951:56759;37954:40;;;;;;;:::i;:::-;;;;;37889:421;2951:56759;;;38162:40;2951:56759;;;;;;38162:7;4373:4;2951:56759;;-1:-1:-1;2951:56759:28;;4304:2;;;;;;;;;38162:40;;:7;:40;;;:::i;:::-;;;;;;;;;;-1:-1:-1;;;38162:40:28;;;37889:421;38126:76;;;38221:27;;38266:29;;37889:421;;38162:40;;;;;;;;2951:56759;38162:40;2951:56759;38162:40;;;;;;;:::i;:::-;;;;;;;;36537:1061;-1:-1:-1;36609:285:28;;;;36654:7;4373:4;2951:56759;;-1:-1:-1;;;36654:20:28;;2951:56759;36654:20;;2951:56759;;36654:20;;2951:56759;;-1:-1:-1;;;;;2951:56759:28;36654:20;;;;;;-1:-1:-1;;;;;36654:20:28;-1:-1:-1;36654:20:28;;;36609:285;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;36642:32;;36638:102;;36609:285;36907:681;36537:1061;36907:681;36947:91;;;;;;;-1:-1:-1;;;;;36947:91:28;;;;36907:681;-1:-1:-1;;;;;2951:56759:28;;;-1:-1:-1;2951:56759:28;;;;;;;;;;;;-1:-1:-1;2951:56759:28;;;;-1:-1:-1;2951:56759:28;;;;-1:-1:-1;2951:56759:28;;;;-1:-1:-1;2951:56759:28;;;;-1:-1:-1;2951:56759:28;;;;-1:-1:-1;2951:56759:28;;;;36106:12;2951:56759;;;;;;37094:10;-1:-1:-1;;;;;;;;;;;2951:56759:28;37094:10;37061:470;;37550:23;;:::o;36947:91::-;37009:9;36294;36997:10;37009:9;:::i;:::-;36947:91;;36638:102;36698:23;36106:12;36638:102;;36654:20;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;36609:285;36794:7;4373:4;;2951:56759;;-1:-1:-1;;;36794:20:28;;2951:56759;36794:20;;2951:56759;;36794:7;2951:56759;;-1:-1:-1;;;;;2951:56759:28;36794:20;;;;;;-1:-1:-1;;;;;36794:20:28;-1:-1:-1;36794:20:28;;;36609:285;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;36782:32;36609:285;36778:102;36838:23;36106:12;36609:285;;36794:20;;;;;;;;;;;;;;:::i;:::-;;;;36294:69;2951:56759;36313:19;2951:56759;;;;;;36313:49;;;;36294:69;;;;36313:49;2951:56759;;;;;;;;;;;36337:24;36313:49;;;36196:27;2951:56759;-1:-1:-1;;;;;2951:56759:28;;36213:10;;36196:27;;35800:4641;;;;;;;;;;;36106:12;;;:26;;35800:4641;2951:56759;;;36208:1;2951:56759;-1:-1:-1;;;;;2951:56759:28;;36196:13;;:27;;;35800:4641;2951:56759;;;36294:9;:14;:69;;;;;;;35800:4641;2951:56759;;;36446:20;;;;;:::i;:::-;36494:32;;;;;;:::i;:::-;36537:1061;;;35800:4641;-1:-1:-1;;36208:1:28;37608:17;;;;37635;;;;37663:20;;;;37693;;;;36208:1;;;;;37795:22;37863:10;;37859:930;;35800:4641;-1:-1:-1;36208:1:28;38834:15;;36106:12;;;38900:26;;;;:::i;:::-;38884:47;;36208:1;38941:19;;-1:-1:-1;;;;;2951:56759:28;;38970:805;;38884:47;39793:28;-1:-1:-1;;;;;39793:28:28;;;;;;:::i;:::-;2951:56759;;;;39793:46;2951:56759;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;-1:-1:-1;;;;;2951:56759:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;36106:12;2951:56759;;;;;37863:10;2951:56759;;;;;39887:313;;2951:56759;;39912:10;-1:-1:-1;;;;;;;;;;;2951:56759:28;39912:10;39887:313;;40412:12;;;;;;;;;;;39912:10;40412:12;:::i;2951:56759::-;-1:-1:-1;;;2951:56759:28;;;;;38970:805;46575:5;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;;;;4304:2;;;;1744:340:19;;2951:56759:28;;;4304:2;;;;;;;;;;46575:5;4304:2;2951:56759;;;46652:9;2951:56759;;4304:2;47902:250;;;;;;;2951:56759;;4304:2;;;47967:67;47902:250;46623:1;2951:56759;4304:2;;;2951:56759;48172:19;39008:43;;39084:32;39105:10;39084:32;:::i;:::-;;;39152:22;-1:-1:-1;;;;;2951:56759:28;;39152:22;;:::i;:::-;;;39202:45;;;;:::i;:::-;39188:59;;39261:454;;;;;-1:-1:-1;39290:7:28;4373:4;-1:-1:-1;;;;;2951:56759:28;39290:66;;;;;2951:56759;;;4304:2;;;;;39290:66;;;;;;;;;;;;;:7;:66;;;:::i;:::-;;;;;;;;;;;;;;39261:454;39375:30;;;;;;;:::i;:::-;;;39261:454;-1:-1:-1;;;;;2951:56759:28;;;;;;38970:805;;;39290:66;;;;;:::i;:::-;2951:56759;;39290:66;;;;39261:454;39444:7;4373:4;-1:-1:-1;;;;;2951:56759:28;39444:66;;;;;36208:1;2951:56759;;4304:2;;;;;39444:66;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;39261:454;4304:2;2951:56759;4304:2;46623:1;4304:2;2951:56759;39625:15;;39659:41;39675:25;;;;;;:::i;39659:41::-;;;39261:454;;39444:66;;;;;36208:1;39444:66;;:::i;:::-;36208:1;;2951:56759;39444:66;;47902:250;4304:2;;;48092:48;47902:250;;38884:47;36208:1;38884:47;;;37859:930;37889:421;;;;;;;;;;;;2951:56759;;37954:40;2951:56759;;;;;;37954:7;4373:4;2951:56759;;36208:1;2951:56759;;4304:2;;;;;;;;;37954:40;;;;;;:::i;:::-;;;;;;;;;;36208:1;;;37954:40;;;37889:421;37918:76;;;38013:30;;38061:26;;37889:421;38340:65;;;:::i;:::-;38419:30;;;;;;:::i;:::-;;;-1:-1:-1;;;;;2951:56759:28;;38468:19;38464:126;;37889:421;38604:32;;;;2951:56759;-1:-1:-1;;;;;2951:56759:28;;38668:31;;;;2951:56759;-1:-1:-1;;;;;2951:56759:28;;38730:31;;;;2951:56759;37859:930;;;38464:126;2951:56759;;-1:-1:-1;;;38514:25:28;;;2951:56759;38514:25;2951:56759;38514:9;-1:-1:-1;;;;;2951:56759:28;38514:25;;;;;;;36208:1;38514:25;;;38464:126;2951:56759;38464:126;2951:56759;;;;36208:1;2951:56759;38514:25;36208:1;2951:56759;38514:25;;;;;;;;;;;;;;:::i;:::-;;;;37954:40;;;;;;;;2951:56759;37954:40;2951:56759;37954:40;;;;;;;:::i;:::-;;;;;;;;37889:421;38162:7;4373:4;;2951:56759;;;-1:-1:-1;;;38162:40:28;;2951:56759;;;;;-1:-1:-1;;;;;2951:56759:28;;;;36208:1;;2951:56759;;38162:40;;2951:56759;;38162:40;;;:::i;:::-;;;;;;;;;;36208:1;;;38162:40;;;37889:421;38126:76;;;38221:27;;38266:29;;37889:421;;38162:40;;;;;;;;2951:56759;38162:40;2951:56759;38162:40;;;;;;;:::i;:::-;;;;;;;;36537:1061;36208:1;36609:285;;;;;;36654:7;4373:4;2951:56759;;-1:-1:-1;;;36654:20:28;;2951:56759;36654:20;;2951:56759;;36654:20;;2951:56759;;-1:-1:-1;;;;;2951:56759:28;36654:20;;;;;;-1:-1:-1;;;;;36654:20:28;36208:1;36654:20;;;36609:285;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;36642:32;;36638:102;;36609:285;36907:681;36537:1061;36907:681;36947:91;;;;;;;;;;-1:-1:-1;;;;;36947:91:28;;;;36907:681;-1:-1:-1;;;;;2951:56759:28;;;36208:1;2951:56759;;;;;;;;;;;;36208:1;2951:56759;;;;36208:1;2951:56759;;;;36208:1;2951:56759;;;;36208:1;2951:56759;;;;36208:1;2951:56759;;;;36208:1;2951:56759;;;;37494:4;2951:56759;;;;37061:470;;2951:56759;;37094:10;-1:-1:-1;;;;;;;;;;;2951:56759:28;37094:10;37061:470;;37550:23;;:::o;36947:91::-;37009:9;36294;36997:10;37009:9;:::i;:::-;36947:91;;36638:102;36698:23;36717:4;36638:102;;36654:20;;;;;;;;;;;;;;:::i;:::-;;;;36609:285;36794:7;4373:4;;2951:56759;;-1:-1:-1;;;36794:20:28;;2951:56759;36794:20;;2951:56759;;36794:7;2951:56759;;-1:-1:-1;;;;;2951:56759:28;36794:20;;;;;;-1:-1:-1;;;;;36794:20:28;36208:1;36794:20;;;36609:285;2951:56759;;-1:-1:-1;;;;;2951:56759:28;;36782:32;36609:285;36778:102;36838:23;36857:4;36609:285;;36794:20;;;;;;;;;;;;;;:::i;:::-;;;;36294:69;2951:56759;36313:19;2951:56759;;;;;;36313:49;;;;36294:69;;;;36313:49;2951:56759;;;;;;;;36337:24;;2951:56759;;36337:24;36313:49;;;36196:27;2951:56759;-1:-1:-1;;;;;2951:56759:28;;36213:10;;36196:27;;2951:56759;;;;;;;;;36106:26;36122:10;;;36106:26;
Swarm Source
ipfs://d6c6dd7d00db3d8928d1597ced112522ac59ce7379c0dc88729955f7d184034c
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.