Contract Overview
[ Download CSV Export ]
Latest 1 internal transaction
Parent Txn Hash | Block | From | To | Value | |||
---|---|---|---|---|---|---|---|
0xec6281cb3fcb6076c7e7556c5247160feaccd7dec3230d0e9a080f4e4ac47ce4 | 1080894 | 306 days 19 hrs ago | Fraxswap: Factory V1 | Contract Creation | 0 GLMR |
[ Download CSV Export ]
Contract Name:
FraxswapPair
Compiler Version
v0.8.13+commit.abaa5c0e
Contract Source Code (Solidity)
/** *Submitted for verification at moonbeam.moonscan.io on 2022-05-22 */ // SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; // Sources flattened with hardhat v2.9.6 https://hardhat.org // File contracts/Fraxswap/core/interfaces/IUniswapV2PairPartialV5.sol interface IUniswapV2PairPartialV5 { // event Approval(address indexed owner, address indexed spender, uint value); // event Transfer(address indexed from, address indexed to, uint value); // // function name() external pure returns (string memory); // function symbol() external pure returns (string memory); // function decimals() external pure returns (uint8); // function totalSupply() external view returns (uint); // function balanceOf(address owner) external view returns (uint); // function allowance(address owner, address spender) external view returns (uint); // // function approve(address spender, uint value) external returns (bool); // function transfer(address to, uint value) external returns (bool); // function transferFrom(address from, address to, uint value) external returns (bool); // // function DOMAIN_SEPARATOR() external view returns (bytes32); // function PERMIT_TYPEHASH() external pure returns (bytes32); // function nonces(address owner) external view returns (uint); // // function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; // TWAMM function longTermSwapFrom0To1(uint256 amount0In, uint256 numberOfTimeIntervals) external returns (uint256 orderId); function longTermSwapFrom1To0(uint256 amount1In, uint256 numberOfTimeIntervals) external returns (uint256 orderId); function cancelLongTermSwap(uint256 orderId) external; function withdrawProceedsFromLongTermSwap(uint256 orderId) external returns (bool is_expired, address rewardTkn, uint256 totalReward); function executeVirtualOrders(uint256 blockTimestamp) external; function orderTimeInterval() external returns (uint256); function getTWAPHistoryLength() external view returns (uint); function getTwammReserves() external view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast, uint112 _twammReserve0, uint112 _twammReserve1); function getReserveAfterTwamm(uint256 blockTimestamp) external view returns (uint112 _reserve0, uint112 _reserve1, uint256 lastVirtualOrderTimestamp, uint112 _twammReserve0, uint112 _twammReserve1); function getNextOrderID() external view returns (uint256); function getOrderIDsForUser(address user) external view returns (uint256[] memory); function getOrderIDsForUserLength(address user) external view returns (uint256); // function getDetailedOrdersForUser(address user, uint256 offset, uint256 limit) external view returns (LongTermOrdersLib.Order[] memory detailed_orders); function twammUpToDate() external view returns (bool); function getTwammState() external view returns (uint256 token0Rate, uint256 token1Rate, uint256 lastVirtualOrderTimestamp, uint256 orderTimeInterval_rtn, uint256 rewardFactorPool0, uint256 rewardFactorPool1); function getTwammSalesRateEnding(uint256 _blockTimestamp) external view returns (uint256 orderPool0SalesRateEnding, uint256 orderPool1SalesRateEnding); function getTwammRewardFactor(uint256 _blockTimestamp) external view returns (uint256 rewardFactorPool0AtTimestamp, uint256 rewardFactorPool1AtTimestamp); function getTwammOrder(uint256 orderId) external view returns (uint256 id, uint256 expirationTimestamp, uint256 saleRate, address owner, address sellTokenAddr, address buyTokenAddr); function getTwammOrderProceedsView(uint256 orderId, uint256 blockTimestamp) external view returns (bool orderExpired, uint256 totalReward); function getTwammOrderProceeds(uint256 orderId) external returns (bool orderExpired, uint256 totalReward); function togglePauseNewSwaps() external; } // File contracts/Fraxswap/core/interfaces/IUniswapV2ERC20V5.sol interface IUniswapV2ERC20V5 { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; } // File contracts/Fraxswap/core/FraxswapERC20.sol // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ========================== FraxswapERC20 =========================== // ==================================================================== // Fraxswap ERC-20 // Inspired by https://www.paradigm.xyz/2021/07/twamm // https://github.com/para-dave/twamm // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Rich Gee: https://github.com/zer0blockchain // Dennis: https://github.com/denett // Logic / Algorithm Ideas // FrankieIsLost: https://github.com/FrankieIsLost // Reviewer(s) / Contributor(s) // Travis Moore: https://github.com/FortisFortuna // Sam Kazemian: https://github.com/samkazemian // Drake Evans: https://github.com/DrakeEvans // Jack Corddry: https://github.com/corddry // Justin Moore: https://github.com/0xJM contract FraxswapERC20 is IUniswapV2ERC20V5 { string public constant override name = 'Fraxswap V1'; string public constant override symbol = 'FS-V1'; uint8 public constant override decimals = 18; uint public override totalSupply; mapping(address => uint) public override balanceOf; mapping(address => mapping(address => uint)) public override allowance; bytes32 public override DOMAIN_SEPARATOR; // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"); bytes32 public constant override PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; mapping(address => uint) public override nonces; constructor() public { uint chainId = block.chainid; DOMAIN_SEPARATOR = keccak256( abi.encode( keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), keccak256(bytes(name)), keccak256(bytes('1')), chainId, address(this) ) ); } function _mint(address to, uint value) internal { totalSupply = totalSupply + value; balanceOf[to] = balanceOf[to] + value; emit Transfer(address(0), to, value); } function _burn(address from, uint value) internal { balanceOf[from] = balanceOf[from] - value; totalSupply = totalSupply - value; emit Transfer(from, address(0), value); } function _approve(address owner, address spender, uint value) private { allowance[owner][spender] = value; emit Approval(owner, spender, value); } function _transfer(address from, address to, uint value) private { balanceOf[from] = balanceOf[from] - value; balanceOf[to] = balanceOf[to] + value; emit Transfer(from, to, value); } function approve(address spender, uint value) external override returns (bool) { _approve(msg.sender, spender, value); return true; } function transfer(address to, uint value) external override returns (bool) { _transfer(msg.sender, to, value); return true; } function transferFrom(address from, address to, uint value) external override returns (bool) { if (allowance[from][msg.sender] != type(uint).max) { allowance[from][msg.sender] = allowance[from][msg.sender] - value; } _transfer(from, to, value); return true; } function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external override { require(deadline >= block.timestamp); // EXPIRED bytes32 digest = keccak256( abi.encodePacked( '\x19\x01', DOMAIN_SEPARATOR, keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline)) ) ); address recoveredAddress = ecrecover(digest, v, r, s); require(recoveredAddress != address(0) && recoveredAddress == owner); // INVALID_SIGNATURE _approve(owner, spender, value); } } // File contracts/Fraxswap/core/libraries/Math.sol // a library for performing various math operations library Math { function min(uint x, uint y) internal pure returns (uint z) { z = x < y ? x : y; } // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method) function sqrt(uint y) internal pure returns (uint z) { if (y > 3) { z = y; uint x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } } // File contracts/Fraxswap/core/libraries/UQ112x112.sol // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) // range: [0, 2**112 - 1] // resolution: 1 / 2**112 library UQ112x112 { uint224 constant Q112 = 2**112; // encode a uint112 as a UQ112x112 function encode(uint112 y) internal pure returns (uint224 z) { z = uint224(y) * Q112; // never overflows } // divide a UQ112x112 by a uint112, returning a UQ112x112 function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) { z = x / uint224(y); } } // File contracts/Fraxswap/core/interfaces/IERC20V5.sol interface IERC20V5 { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); } // File contracts/Fraxswap/core/interfaces/IUniswapV2FactoryV5.sol interface IUniswapV2FactoryV5 { event PairCreated(address indexed token0, address indexed token1, address pair, uint); function feeTo() external view returns (address); function feeToSetter() external view returns (address); function getPair(address tokenA, address tokenB) external view returns (address pair); function allPairs(uint) external view returns (address pair); function allPairsLength() external view returns (uint); function createPair(address tokenA, address tokenB) external returns (address pair); function setFeeTo(address) external; function setFeeToSetter(address) external; } // File contracts/Fraxswap/core/interfaces/IUniswapV2CalleeV5.sol interface IUniswapV2CalleeV5 { function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external; } // File contracts/Fraxswap/libraries/TransferHelper.sol // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeApprove: approve failed' ); } function safeTransfer( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeTransfer: transfer failed' ); } function safeTransferFrom( address token, address from, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::transferFrom: transferFrom failed' ); } function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, 'TransferHelper::safeTransferETH: ETH transfer failed'); } } // File contracts/Fraxswap/twamm/ExecVirtualOrders.sol // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ======================= ExecVirtualOrdersLib ======================= // ==================================================================== // TWAMM logic for executing the virtual orders // Inspired by https://www.paradigm.xyz/2021/07/twamm // https://github.com/para-dave/twamm // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Rich Gee: https://github.com/zer0blockchain // Dennis: https://github.com/denett // Logic / Algorithm Ideas // FrankieIsLost: https://github.com/FrankieIsLost // Reviewer(s) / Contributor(s) // Travis Moore: https://github.com/FortisFortuna // Sam Kazemian: https://github.com/samkazemian // Drake Evans: https://github.com/DrakeEvans // Jack Corddry: https://github.com/corddry // Justin Moore: https://github.com/0xJM ///@notice This library handles the execution of long term orders. library ExecVirtualOrdersLib { ///@notice computes the result of virtual trades by the token pools function computeVirtualBalances( uint256 token0Start, uint256 token1Start, uint256 token0In, uint256 token1In) internal pure returns (uint256 token0Out, uint256 token1Out) { token0Out = 0; token1Out = 0; //if no tokens are sold to the pool, we don't need to execute any orders if (token0In <= 1 && token1In <= 1) { // do nothing } //in the case where only one pool is selling, we just perform a normal swap else if (token0In <= 1) { //constant product formula uint token1InWithFee = token1In * 997; token0Out = token0Start * token1InWithFee / ((token1Start * 1000) + token1InWithFee); } else if (token1In <= 1) { //contant product formula uint token0InWithFee = token0In * 997; token1Out = token1Start * token0InWithFee / ((token0Start * 1000) + token0InWithFee); } //when both pools sell, we use the TWAMM formula else { uint256 newToken0 = token0Start + (token0In * 997 / 1000); uint256 newToken1 = token1Start + (token1In * 997 / 1000); token0Out = newToken0 - (token1Start * (newToken0) / (newToken1)); token1Out = newToken1 - (token0Start * (newToken1) / (newToken0)); } } } // File contracts/Fraxswap/twamm/LongTermOrders.sol // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // ========================= LongTermOrdersLib ======================== // ==================================================================== // TWAMM long term order execution logic // Inspired by https://www.paradigm.xyz/2021/07/twamm // https://github.com/para-dave/twamm // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Rich Gee: https://github.com/zer0blockchain // Dennis: https://github.com/denett // Logic / Algorithm Ideas // FrankieIsLost: https://github.com/FrankieIsLost // Reviewer(s) / Contributor(s) // Travis Moore: https://github.com/FortisFortuna // Sam Kazemian: https://github.com/samkazemian // Drake Evans: https://github.com/DrakeEvans // Jack Corddry: https://github.com/corddry // Justin Moore: https://github.com/0xJM ///@notice This library handles the state and execution of long term orders. library LongTermOrdersLib { using LongTermOrdersLib for OrderPool; /// --------------------------- /// ----- LongTerm Orders ----- /// --------------------------- uint112 internal constant SELL_RATE_ADDITIONAL_PRECISION = 1000000; ///@notice information associated with a long term order ///fields should NOT be changed after Order struct is created struct Order { uint256 id; uint256 expirationTimestamp; uint256 saleRate; address owner; address sellTokenAddr; address buyTokenAddr; bool isComplete; } ///@notice structure contains full state related to long term orders struct LongTermOrders { ///@notice minimum time interval between order expiries uint256 orderTimeInterval; ///@notice last virtual orders were executed immediately before this block.timestamp uint256 lastVirtualOrderTimestamp; ///@notice token pair being traded in embedded amm address token0; address token1; ///@notice mapping from token address to pool that is selling that token ///we maintain two order pools, one for each token that is tradable in the AMM OrderPool OrderPool0; OrderPool OrderPool1; ///@notice incrementing counter for order ids, this is the next order id uint256 orderId; ///@notice mapping from order ids to Orders mapping(uint256 => Order) orderMap; } struct ExecuteVirtualOrdersResult { uint112 newReserve0; uint112 newReserve1; uint256 newTwammReserve0; uint256 newTwammReserve1; uint256 token0Bought; uint256 token1Bought; uint256 token0Sold; uint256 token1Sold; uint256 expiries; } ///@notice initialize state function initialize(LongTermOrders storage longTermOrders, address token0, address token1, uint256 lastVirtualOrderTimestamp, uint256 orderTimeInterval) internal { longTermOrders.token0 = token0; longTermOrders.token1 = token1; longTermOrders.lastVirtualOrderTimestamp = lastVirtualOrderTimestamp; longTermOrders.orderTimeInterval = orderTimeInterval; } ///@notice get the OrderPool for this token function getOrderPool(LongTermOrders storage longTermOrders, address token) internal view returns (OrderPool storage orderPool) { orderPool = token == longTermOrders.token0 ? longTermOrders.OrderPool0 : longTermOrders.OrderPool1; } ///@notice swap token 0 for token 1. Amount represents total amount being sold, numberOfTimeIntervals determines when order expires function longTermSwapFrom0To1(LongTermOrders storage longTermOrders, uint256 amount0, uint256 numberOfTimeIntervals) internal returns (uint256) { return performLongTermSwap(longTermOrders, longTermOrders.token0, longTermOrders.token1, amount0, numberOfTimeIntervals); } ///@notice swap token 1 for token 0. Amount represents total amount being sold, numberOfTimeIntervals determines when order expires function longTermSwapFrom1To0(LongTermOrders storage longTermOrders, uint256 amount1, uint256 numberOfTimeIntervals) internal returns (uint256) { return performLongTermSwap(longTermOrders, longTermOrders.token1, longTermOrders.token0, amount1, numberOfTimeIntervals); } ///@notice adds long term swap to order pool function performLongTermSwap(LongTermOrders storage longTermOrders, address from, address to, uint256 amount, uint256 numberOfTimeIntervals) private returns (uint256) { // make sure to update virtual order state (before calling this function) //determine the selling rate based on number of blocks to expiry and total amount uint256 currentTime = block.timestamp; uint256 lastExpiryTimestamp = currentTime - (currentTime % longTermOrders.orderTimeInterval); uint256 orderExpiry = longTermOrders.orderTimeInterval * (numberOfTimeIntervals + 1) + lastExpiryTimestamp; uint256 sellingRate = SELL_RATE_ADDITIONAL_PRECISION * amount / (orderExpiry - currentTime); require(sellingRate > 0); // tokenRate cannot be zero //add order to correct pool OrderPool storage orderPool = getOrderPool(longTermOrders, from); orderPoolDepositOrder(orderPool, longTermOrders.orderId, sellingRate, orderExpiry); //add to order map longTermOrders.orderMap[longTermOrders.orderId] = Order(longTermOrders.orderId, orderExpiry, sellingRate, msg.sender, from, to, false); return longTermOrders.orderId++; } ///@notice cancel long term swap, pay out unsold tokens and well as purchased tokens function cancelLongTermSwap(LongTermOrders storage longTermOrders, uint256 orderId) internal returns (address sellToken, uint256 unsoldAmount, address buyToken, uint256 purchasedAmount) { // make sure to update virtual order state (before calling this function) Order storage order = longTermOrders.orderMap[orderId]; buyToken = order.buyTokenAddr; sellToken = order.sellTokenAddr; OrderPool storage orderPool = getOrderPool(longTermOrders, sellToken); (unsoldAmount, purchasedAmount) = orderPoolCancelOrder(orderPool, orderId, longTermOrders.lastVirtualOrderTimestamp); require(order.owner == msg.sender && (unsoldAmount > 0 || purchasedAmount > 0)); // owner and amounts check } ///@notice withdraw proceeds from a long term swap (can be expired or ongoing) function withdrawProceedsFromLongTermSwap(LongTermOrders storage longTermOrders, uint256 orderId) internal returns (address proceedToken, uint256 proceeds, bool orderExpired) { // make sure to update virtual order state (before calling this function) Order storage order = longTermOrders.orderMap[orderId]; proceedToken = order.buyTokenAddr; OrderPool storage orderPool = getOrderPool(longTermOrders, order.sellTokenAddr); (proceeds, orderExpired) = orderPoolWithdrawProceeds(orderPool, orderId, longTermOrders.lastVirtualOrderTimestamp); require(order.owner == msg.sender && proceeds > 0); // owner and amounts check } ///@notice executes all virtual orders between current lastVirtualOrderTimestamp and blockTimestamp //also handles orders that expire at end of final blockTimestamp. This assumes that no orders expire inside the given interval function executeVirtualTradesAndOrderExpiries( ExecuteVirtualOrdersResult memory reserveResult, uint256 token0SellAmount, uint256 token1SellAmount ) private view returns (uint256 token0Out, uint256 token1Out) { //initial amm balance uint256 bal0 = reserveResult.newReserve0 + reserveResult.newTwammReserve0; uint256 bal1 = reserveResult.newReserve1 + reserveResult.newTwammReserve1; //updated balances from sales (token0Out, token1Out) = ExecVirtualOrdersLib.computeVirtualBalances( reserveResult.newReserve0, reserveResult.newReserve1, token0SellAmount, token1SellAmount ); //update balances reserves reserveResult.newTwammReserve0 = reserveResult.newTwammReserve0 + token0Out - token0SellAmount; reserveResult.newTwammReserve1 = reserveResult.newTwammReserve1 + token1Out - token1SellAmount; reserveResult.newReserve0 = uint112(bal0 - reserveResult.newTwammReserve0); // calculate reserve0 incl LP fees reserveResult.newReserve1 = uint112(bal1 - reserveResult.newTwammReserve1); // calculate reserve1 incl LP fees reserveResult.token0Bought += token0Out; reserveResult.token1Bought += token1Out; reserveResult.token0Sold += token0SellAmount; reserveResult.token1Sold += token1SellAmount; reserveResult.expiries += 1; } ///@notice executes all virtual orders until blockTimestamp is reached. function executeVirtualOrdersUntilTimestamp(LongTermOrders storage longTermOrders, uint256 blockTimestamp, ExecuteVirtualOrdersResult memory reserveResult) internal { uint256 lastVirtualOrderTimestampLocal = longTermOrders.lastVirtualOrderTimestamp; // save gas uint256 orderTimeInterval = longTermOrders.orderTimeInterval; // save gas uint256 nextExpiryBlockTimestamp = lastVirtualOrderTimestampLocal - (lastVirtualOrderTimestampLocal % orderTimeInterval) + orderTimeInterval; //iterate through time intervals eligible for order expiries, moving state forward OrderPool storage orderPool0 = longTermOrders.OrderPool0; OrderPool storage orderPool1 = longTermOrders.OrderPool1; while (nextExpiryBlockTimestamp < blockTimestamp) { // Optimization for skipping blocks with no expiry if (orderPool0.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp] > 0 || orderPool1.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp] > 0) { //amount sold from virtual trades uint256 blockTimestampElapsed = nextExpiryBlockTimestamp - lastVirtualOrderTimestampLocal; uint256 token0SellAmount = orderPool0.currentSalesRate * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION; uint256 token1SellAmount = orderPool1.currentSalesRate * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION; (uint256 token0Out, uint256 token1Out) = executeVirtualTradesAndOrderExpiries(reserveResult, token0SellAmount, token1SellAmount); //distribute proceeds to pools. make sure to call this before orderPoolUpdateStateFromTimestampExpiry. orderPoolDistributePayment(orderPool0, token1Out); orderPoolDistributePayment(orderPool1, token0Out); //handle orders expiring at end of interval. call orderPoolDistributePayment before calling this. orderPoolUpdateStateFromTimestampExpiry(orderPool0, nextExpiryBlockTimestamp); orderPoolUpdateStateFromTimestampExpiry(orderPool1, nextExpiryBlockTimestamp); lastVirtualOrderTimestampLocal = nextExpiryBlockTimestamp; } nextExpiryBlockTimestamp += orderTimeInterval; } //finally, move state to current blockTimestamp if necessary if (lastVirtualOrderTimestampLocal != blockTimestamp) { //amount sold from virtual trades uint256 blockTimestampElapsed = blockTimestamp - lastVirtualOrderTimestampLocal; uint256 token0SellAmount = orderPool0.currentSalesRate * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION; uint256 token1SellAmount = orderPool1.currentSalesRate * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION; (uint256 token0Out, uint256 token1Out) = executeVirtualTradesAndOrderExpiries(reserveResult, token0SellAmount, token1SellAmount); //distribute proceeds to pools orderPoolDistributePayment(orderPool0, token1Out); orderPoolDistributePayment(orderPool1, token0Out); // skip call to orderPoolUpdateStateFromTimestampExpiry, this will not be an expiry timestamp. save gas } longTermOrders.lastVirtualOrderTimestamp = blockTimestamp; } ///@notice executes all virtual orders until blockTimestamp is reached (AS A VIEW) function executeVirtualOrdersUntilTimestampView(LongTermOrders storage longTermOrders, uint256 blockTimestamp, ExecuteVirtualOrdersResult memory reserveResult) internal view { uint256 lastVirtualOrderTimestampLocal = longTermOrders.lastVirtualOrderTimestamp; // save gas uint256 orderTimeInterval = longTermOrders.orderTimeInterval; // save gas uint256 nextExpiryBlockTimestamp = lastVirtualOrderTimestampLocal - (lastVirtualOrderTimestampLocal % orderTimeInterval) + orderTimeInterval; //iterate through time intervals eligible for order expiries, moving state forward OrderPool storage orderPool0 = longTermOrders.OrderPool0; OrderPool storage orderPool1 = longTermOrders.OrderPool1; // currentSales for each pool is mutated in the non-view (mutate locally) uint256 currentSalesRate0 = orderPool0.currentSalesRate; uint256 currentSalesRate1 = orderPool1.currentSalesRate; while (nextExpiryBlockTimestamp < blockTimestamp) { // Optimization for skipping blocks with no expiry if (orderPool0.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp] > 0 || orderPool1.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp] > 0) { //amount sold from virtual trades uint256 blockTimestampElapsed = nextExpiryBlockTimestamp - lastVirtualOrderTimestampLocal; uint256 token0SellAmount = currentSalesRate0 * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION; uint256 token1SellAmount = currentSalesRate1 * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION; executeVirtualTradesAndOrderExpiries(reserveResult, token0SellAmount, token1SellAmount); currentSalesRate0 -= orderPool0.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp]; currentSalesRate1 -= orderPool1.salesRateEndingPerTimeInterval[nextExpiryBlockTimestamp]; lastVirtualOrderTimestampLocal = nextExpiryBlockTimestamp; } nextExpiryBlockTimestamp += orderTimeInterval; } //finally, move state to current blockTimestamp if necessary if (lastVirtualOrderTimestampLocal != blockTimestamp) { //amount sold from virtual trades uint256 blockTimestampElapsed = blockTimestamp - lastVirtualOrderTimestampLocal; uint256 token0SellAmount = currentSalesRate0 * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION; uint256 token1SellAmount = currentSalesRate1 * blockTimestampElapsed / SELL_RATE_ADDITIONAL_PRECISION; executeVirtualTradesAndOrderExpiries(reserveResult, token0SellAmount, token1SellAmount); } } /// --------------------------- /// -------- OrderPool -------- /// --------------------------- ///@notice An Order Pool is an abstraction for a pool of long term orders that sells a token at a constant rate to the embedded AMM. ///the order pool handles the logic for distributing the proceeds from these sales to the owners of the long term orders through a modified ///version of the staking algorithm from https://uploads-ssl.webflow.com/5ad71ffeb79acc67c8bcdaba/5ad8d1193a40977462982470_scalable-reward-distribution-paper.pdf uint256 constant Q112 = 2**112; ///@notice you can think of this as a staking pool where all long term orders are staked. /// The pool is paid when virtual long term orders are executed, and each order is paid proportionally /// by the order's sale rate per time intervals struct OrderPool { ///@notice current rate that tokens are being sold (per time interval) uint256 currentSalesRate; ///@notice sum of (salesProceeds_k / salesRate_k) over every period k. Stored as a fixed precision floating point number uint256 rewardFactor; ///@notice this maps time interval numbers to the cumulative sales rate of orders that expire on that block (time interval) mapping(uint256 => uint256) salesRateEndingPerTimeInterval; ///@notice map order ids to the block timestamp in which they expire mapping(uint256 => uint256) orderExpiry; ///@notice map order ids to their sales rate mapping(uint256 => uint256) salesRate; ///@notice reward factor per order at time of submission mapping(uint256 => uint256) rewardFactorAtSubmission; ///@notice reward factor at a specific time interval mapping(uint256 => uint256) rewardFactorAtTimestamp; } ///@notice distribute payment amount to pool (in the case of TWAMM, proceeds from trades against amm) function orderPoolDistributePayment(OrderPool storage orderPool, uint256 amount) internal { if (orderPool.currentSalesRate != 0) { unchecked { // Addition is with overflow orderPool.rewardFactor += amount * Q112 * SELL_RATE_ADDITIONAL_PRECISION / orderPool.currentSalesRate; } } } ///@notice deposit an order into the order pool. function orderPoolDepositOrder(OrderPool storage orderPool, uint256 orderId, uint256 amountPerInterval, uint256 orderExpiry) internal { orderPool.currentSalesRate += amountPerInterval; orderPool.rewardFactorAtSubmission[orderId] = orderPool.rewardFactor; orderPool.orderExpiry[orderId] = orderExpiry; orderPool.salesRate[orderId] = amountPerInterval; orderPool.salesRateEndingPerTimeInterval[orderExpiry] += amountPerInterval; } ///@notice when orders expire after a given timestamp, we need to update the state of the pool function orderPoolUpdateStateFromTimestampExpiry(OrderPool storage orderPool, uint256 blockTimestamp) internal { orderPool.currentSalesRate -= orderPool.salesRateEndingPerTimeInterval[blockTimestamp]; orderPool.rewardFactorAtTimestamp[blockTimestamp] = orderPool.rewardFactor; } ///@notice cancel order and remove from the order pool function orderPoolCancelOrder(OrderPool storage orderPool, uint256 orderId, uint256 blockTimestamp) internal returns (uint256 unsoldAmount, uint256 purchasedAmount) { uint256 expiry = orderPool.orderExpiry[orderId]; require(expiry > blockTimestamp); //calculate amount that wasn't sold, and needs to be returned uint256 salesRate = orderPool.salesRate[orderId]; unsoldAmount = (expiry - blockTimestamp) * salesRate / SELL_RATE_ADDITIONAL_PRECISION; //calculate amount of other token that was purchased unchecked { // subtraction is with underflow purchasedAmount = ((orderPool.rewardFactor - orderPool.rewardFactorAtSubmission[orderId]) * salesRate / SELL_RATE_ADDITIONAL_PRECISION) / Q112; } //update state orderPool.currentSalesRate -= salesRate; orderPool.salesRate[orderId] = 0; orderPool.orderExpiry[orderId] = 0; orderPool.salesRateEndingPerTimeInterval[expiry] -= salesRate; } ///@notice withdraw proceeds from pool for a given order. This can be done before or after the order has expired. //If the order has expired, we calculate the reward factor at time of expiry. If order has not yet expired, we //use current reward factor, and update the reward factor at time of staking (effectively creating a new order) function orderPoolWithdrawProceeds(OrderPool storage orderPool, uint256 orderId, uint256 blockTimestamp) internal returns (uint256 totalReward, bool orderExpired) { (orderExpired, totalReward) = orderPoolGetProceeds(orderPool, orderId, blockTimestamp); if (orderExpired) { //remove stake orderPool.salesRate[orderId] = 0; } //if order has not yet expired, we just adjust the start else { orderPool.rewardFactorAtSubmission[orderId] = orderPool.rewardFactor; } } ///@notice view function for getting the current proceeds for the given order function orderPoolGetProceeds(OrderPool storage orderPool, uint256 orderId, uint256 blockTimestamp) internal view returns (bool orderExpired, uint256 totalReward) { uint256 stakedAmount = orderPool.salesRate[orderId]; require(stakedAmount > 0); uint256 orderExpiry = orderPool.orderExpiry[orderId]; uint256 rewardFactorAtSubmission = orderPool.rewardFactorAtSubmission[orderId]; //if order has expired, we need to calculate the reward factor at expiry if (blockTimestamp > orderExpiry) { uint256 rewardFactorAtExpiry = orderPool.rewardFactorAtTimestamp[orderExpiry]; unchecked { // subtraction is with underflow totalReward = ((rewardFactorAtExpiry - rewardFactorAtSubmission) * stakedAmount / SELL_RATE_ADDITIONAL_PRECISION) / Q112; } orderExpired = true; } else { unchecked { // subtraction is with underflow totalReward = ((orderPool.rewardFactor - rewardFactorAtSubmission) * stakedAmount / SELL_RATE_ADDITIONAL_PRECISION) / Q112; } orderExpired = false; } } } // File contracts/Fraxswap/core/FraxswapPair.sol // ==================================================================== // | ______ _______ | // | / _____________ __ __ / ____(_____ ____ _____ ________ | // | / /_ / ___/ __ `| |/_/ / /_ / / __ \/ __ `/ __ \/ ___/ _ \ | // | / __/ / / / /_/ _> < / __/ / / / / / /_/ / / / / /__/ __/ | // | /_/ /_/ \__,_/_/|_| /_/ /_/_/ /_/\__,_/_/ /_/\___/\___/ | // | | // ==================================================================== // =========================== FraxswapPair =========================== // ==================================================================== // TWAMM LP Pair Token // Inspired by https://www.paradigm.xyz/2021/07/twamm // https://github.com/para-dave/twamm // Frax Finance: https://github.com/FraxFinance // Primary Author(s) // Rich Gee: https://github.com/zer0blockchain // Dennis: https://github.com/denett // Logic / Algorithm Ideas // FrankieIsLost: https://github.com/FrankieIsLost // Reviewer(s) / Contributor(s) // Travis Moore: https://github.com/FortisFortuna // Sam Kazemian: https://github.com/samkazemian // Drake Evans: https://github.com/DrakeEvans // Jack Corddry: https://github.com/corddry // Justin Moore: https://github.com/0xJM contract FraxswapPair is IUniswapV2PairPartialV5, FraxswapERC20 { using UQ112x112 for uint224; using LongTermOrdersLib for LongTermOrdersLib.LongTermOrders; using LongTermOrdersLib for LongTermOrdersLib.ExecuteVirtualOrdersResult; /// --------------------------- /// -----TWAMM Parameters ----- /// --------------------------- // address public owner_address; ///@notice time interval that are eligible for order expiry (to align expiries) uint256 public orderTimeInterval = 3600; ///@notice data structure to handle long term orders LongTermOrdersLib.LongTermOrders internal longTermOrders; uint112 public twammReserve0; uint112 public twammReserve1; bool public newSwapsPaused; modifier execVirtualOrders() { executeVirtualOrdersInternal(block.timestamp); _; } /// --------------------------- /// -------- Modifiers -------- /// --------------------------- ///@notice Throws if called by any account other than the owner. modifier onlyOwner() { require(IUniswapV2FactoryV5(factory).feeToSetter() == msg.sender); // NOT OWNER _; } ///@notice Checks if new swaps are paused. If they are, only allow closing of existing ones. modifier isNotPaused() { require(newSwapsPaused == false); // NEW LT ORDERS PAUSED _; } /// --------------------------- /// --------- Events ---------- /// --------------------------- ///@notice An event emitted when a long term swap from token0 to token1 is performed event LongTermSwap0To1(address indexed addr, uint256 orderId, uint256 amount0In, uint256 numberOfTimeIntervals); ///@notice An event emitted when a long term swap from token1 to token0 is performed event LongTermSwap1To0(address indexed addr, uint256 orderId, uint256 amount1In, uint256 numberOfTimeIntervals); ///@notice An event emitted when a long term swap is cancelled event CancelLongTermOrder(address indexed addr, uint256 orderId, address sellToken, uint256 unsoldAmount, address buyToken, uint256 purchasedAmount); ///@notice An event emitted when a long term swap is withdrawn event WithdrawProceedsFromLongTermOrder(address indexed addr, uint256 orderId, address indexed proceedToken, uint256 proceeds, bool orderExpired); ///@notice An event emitted when virtual orders are executed event VirtualOrderExecution(uint256 blocktimestamp, uint256 newReserve0, uint256 newReserve1, uint256 newTwammReserve0, uint256 newTwammReserve1, uint256 token0Bought, uint256 token1Bought, uint256 token0Sold, uint256 token1Sold, uint256 expiries); /// ------------------------------- /// -----UNISWAPV2 Parameters ----- /// ------------------------------- uint public constant override MINIMUM_LIQUIDITY = 10 ** 3; bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)'))); address public override factory; address public override token0; address public override token1; uint112 private reserve0; // uses single storage slot, accessible via getReserves uint112 private reserve1; // uses single storage slot, accessible via getReserves uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves uint public override kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event // Track order IDs mapping(address => uint256[]) public orderIDsForUser; TWAPObservation[] public TWAPObservationHistory; struct TWAPObservation { uint timestamp; uint price0CumulativeLast; uint price1CumulativeLast; } function price0CumulativeLast() public view override returns (uint){ return TWAPObservationHistory.length > 0 ? TWAPObservationHistory[TWAPObservationHistory.length - 1].price0CumulativeLast : 0; } function price1CumulativeLast() public view override returns (uint){ return TWAPObservationHistory.length > 0 ? TWAPObservationHistory[TWAPObservationHistory.length - 1].price1CumulativeLast : 0; } function getTWAPHistoryLength() public view override returns (uint){ return TWAPObservationHistory.length; } uint private unlocked = 1; modifier lock() { require(unlocked == 1); // LOCKED unlocked = 0; _; unlocked = 1; } function getOrderIDsForUser(address user) external view returns (uint256[] memory) { return orderIDsForUser[user]; } function getOrderIDsForUserLength(address user) external view returns (uint256) { return orderIDsForUser[user].length; } function getDetailedOrdersForUser(address user, uint256 offset, uint256 limit) external view returns (LongTermOrdersLib.Order[] memory detailed_orders) { uint256[] memory order_ids = orderIDsForUser[user]; uint256 length_remaining = order_ids.length - offset; uint256 limit_to_use = Math.min(limit, length_remaining); detailed_orders = new LongTermOrdersLib.Order[](limit_to_use); for (uint256 i = 0; i < limit_to_use; i++){ detailed_orders[i] = longTermOrders.orderMap[order_ids[offset + i]]; } } function getReserves() public override view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) { return (reserve0, reserve1, blockTimestampLast); } function getTwammReserves() public override view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast, uint112 _twammReserve0, uint112 _twammReserve1) { return (reserve0, reserve1, blockTimestampLast, twammReserve0, twammReserve1); } function _safeTransfer(address token, address to, uint value) private { (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value)); require(success && (data.length == 0 || abi.decode(data, (bool))), "EC01"); // TRANSFER_FAILED } constructor() public { factory = msg.sender; // owner_address = IUniswapV2FactoryV5(factory).feeToSetter(); } // called once by the factory at time of deployment function initialize(address _token0, address _token1) external override { require(msg.sender == factory); // FORBIDDEN // sufficient check token0 = _token0; token1 = _token1; // TWAMM longTermOrders.initialize(_token0, _token1, block.timestamp, orderTimeInterval); } // update reserves and, on the first call per block, price accumulators function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private { require(balance0 + twammReserve0 <= type(uint112).max && balance1 + twammReserve1 <= type(uint112).max, "EC02"); // OVERFLOW uint32 blockTimestamp = uint32(block.timestamp % 2 ** 32); uint32 timeElapsed; unchecked{ timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) { // * never overflows, and + overflow is desired TWAPObservationHistory.push( TWAPObservation( blockTimestamp, price0CumulativeLast() + uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed, price1CumulativeLast() + uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed ) ); } } reserve0 = uint112(balance0); reserve1 = uint112(balance1); blockTimestampLast = blockTimestamp; emit Sync(reserve0, reserve1); } // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k) function _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) { address feeTo = IUniswapV2FactoryV5(factory).feeTo(); feeOn = feeTo != address(0); uint _kLast = kLast; // gas savings if (feeOn) { if (_kLast != 0) { uint rootK = Math.sqrt(uint(_reserve0) * _reserve1); uint rootKLast = Math.sqrt(_kLast); if (rootK > rootKLast) { uint numerator = totalSupply * (rootK - rootKLast); uint denominator = (rootK * 5) + rootKLast; uint liquidity = numerator / denominator; if (liquidity > 0) _mint(feeTo, liquidity); } } } else if (_kLast != 0) { kLast = 0; } } // this low-level function should be called from a contract which performs important safety checks function mint(address to) external override lock execVirtualOrders returns (uint liquidity) { (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings uint balance0 = IERC20V5(token0).balanceOf(address(this)) - twammReserve0; uint balance1 = IERC20V5(token1).balanceOf(address(this)) - twammReserve1; uint amount0 = balance0 - _reserve0; uint amount1 = balance1 - _reserve1; bool feeOn = _mintFee(_reserve0, _reserve1); uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee if (_totalSupply == 0) { liquidity = Math.sqrt(amount0 * amount1) - MINIMUM_LIQUIDITY; _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens } else { liquidity = Math.min(amount0 * _totalSupply / _reserve0, amount1 * _totalSupply / _reserve1); } require(liquidity > 0); // INSUFFICIENT_LIQUIDITY_MINTED _mint(to, liquidity); _update(balance0, balance1, _reserve0, _reserve1); if (feeOn) kLast = uint(reserve0) * reserve1; // reserve0 and reserve1 are up-to-date emit Mint(msg.sender, amount0, amount1); } // this low-level function should be called from a contract which performs important safety checks function burn(address to) external override lock execVirtualOrders returns (uint amount0, uint amount1) { (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings address _token0 = token0; // gas savings address _token1 = token1; // gas savings uint balance0 = IERC20V5(_token0).balanceOf(address(this)) - twammReserve0; uint balance1 = IERC20V5(_token1).balanceOf(address(this)) - twammReserve1; uint liquidity = balanceOf[address(this)]; bool feeOn = _mintFee(_reserve0, _reserve1); uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee amount0 = liquidity * balance0 / _totalSupply; // using balances ensures pro-rata distribution amount1 = liquidity * balance1 / _totalSupply; // using balances ensures pro-rata distribution require(amount0 > 0 && amount1 > 0); // INSUFFICIENT_LIQUIDITY_BURNED _burn(address(this), liquidity); _safeTransfer(_token0, to, amount0); _safeTransfer(_token1, to, amount1); balance0 = IERC20V5(_token0).balanceOf(address(this)) - twammReserve0; balance1 = IERC20V5(_token1).balanceOf(address(this)) - twammReserve1; _update(balance0, balance1, _reserve0, _reserve1); if (feeOn) kLast = uint(reserve0) * reserve1; // reserve0 and reserve1 are up-to-date emit Burn(msg.sender, amount0, amount1, to); } // this low-level function should be called from a contract which performs important safety checks function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external override lock execVirtualOrders { require(amount0Out > 0 || amount1Out > 0, "EC03"); // INSUFFICIENT_OUTPUT_AMOUNT (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings require(amount0Out < _reserve0 && amount1Out < _reserve1, "EC04"); // INSUFFICIENT_LIQUIDITY uint balance0; uint balance1; {// scope for _token{0,1}, avoids stack too deep errors address _token0 = token0; address _token1 = token1; require(to != _token0 && to != _token1, "EC05"); // INVALID_TO if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens if (data.length > 0) IUniswapV2CalleeV5(to).uniswapV2Call(msg.sender, amount0Out, amount1Out, data); balance0 = IERC20V5(_token0).balanceOf(address(this)) - twammReserve0; balance1 = IERC20V5(_token1).balanceOf(address(this)) - twammReserve1; } uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0; uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0; require(amount0In > 0 || amount1In > 0, "EC06"); // INSUFFICIENT_INPUT_AMOUNT {// scope for reserve{0,1}Adjusted, avoids stack too deep errors uint balance0Adjusted = (balance0 * 1000) - (amount0In * 3); uint balance1Adjusted = (balance1 * 1000) - (amount1In * 3); require(balance0Adjusted * balance1Adjusted >= uint(_reserve0) * _reserve1 * (1000 ** 2), 'K'); } _update(balance0, balance1, _reserve0, _reserve1); emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to); } // force balances to match reserves function skim(address to) external override lock execVirtualOrders { address _token0 = token0; // gas savings address _token1 = token1; // gas savings _safeTransfer(_token0, to, IERC20V5(_token0).balanceOf(address(this)) - (reserve0 + twammReserve0)); _safeTransfer(_token1, to, IERC20V5(_token1).balanceOf(address(this)) - (reserve1 + twammReserve1)); } // force reserves to match balances function sync() external override lock execVirtualOrders { _update( IERC20V5(token0).balanceOf(address(this)) - twammReserve0, IERC20V5(token1).balanceOf(address(this)) - twammReserve1, reserve0, reserve1 ); } // TWAMM ///@notice calculate the amount in for token0 using the balance diff to handle feeOnTransfer tokens function transferAmount0In(uint amount0In) internal returns(uint256){ // prev balance uint bal0 = IERC20V5(token0).balanceOf(address(this)); // transfer amount to contract TransferHelper.safeTransferFrom(token0, msg.sender, address(this), amount0In); // balance change return IERC20V5(token0).balanceOf(address(this)) - bal0; } ///@notice calculate the amount in for token1 using the balance diff to handle feeOnTransfer tokens function transferAmount1In(uint amount1In) internal returns(uint256){ // prev balance uint bal1 = IERC20V5(token1).balanceOf(address(this)); // transfer amount to contract TransferHelper.safeTransferFrom(token1, msg.sender, address(this), amount1In); // balance change return IERC20V5(token1).balanceOf(address(this)) - bal1; } ///@notice create a long term order to swap from token0 ///@param amount0In total amount of token0 to swap ///@param numberOfTimeIntervals number of time intervals over which to execute long term order function longTermSwapFrom0To1(uint256 amount0In, uint256 numberOfTimeIntervals) external lock isNotPaused execVirtualOrders returns (uint256 orderId) { uint amount0 = transferAmount0In(amount0In); twammReserve0 += uint112(amount0); require(uint256(reserve0) + twammReserve0 <= type(uint112).max); // OVERFLOW orderId = longTermOrders.longTermSwapFrom0To1(amount0, numberOfTimeIntervals); orderIDsForUser[msg.sender].push(orderId); emit LongTermSwap0To1(msg.sender, orderId, amount0, numberOfTimeIntervals); } ///@notice create a long term order to swap from token1 ///@param amount1In total amount of token1 to swap ///@param numberOfTimeIntervals number of time intervals over which to execute long term order function longTermSwapFrom1To0(uint256 amount1In, uint256 numberOfTimeIntervals) external lock isNotPaused execVirtualOrders returns (uint256 orderId) { uint amount1 = transferAmount1In(amount1In); twammReserve1 += uint112(amount1); require(uint256(reserve1) + twammReserve1 <= type(uint112).max); // OVERFLOW orderId = longTermOrders.longTermSwapFrom1To0(amount1, numberOfTimeIntervals); orderIDsForUser[msg.sender].push(orderId); emit LongTermSwap1To0(msg.sender, orderId, amount1, numberOfTimeIntervals); } ///@notice stop the execution of a long term order function cancelLongTermSwap(uint256 orderId) external lock execVirtualOrders { (address sellToken, uint256 unsoldAmount, address buyToken, uint256 purchasedAmount) = longTermOrders.cancelLongTermSwap(orderId); bool buyToken0 = buyToken == token0; twammReserve0 -= uint112(buyToken0 ? purchasedAmount : unsoldAmount); twammReserve1 -= uint112(buyToken0 ? unsoldAmount : purchasedAmount); // update order. Used for tracking / informational longTermOrders.orderMap[orderId].isComplete = true; // transfer to owner of order _safeTransfer(buyToken, msg.sender, purchasedAmount); _safeTransfer(sellToken, msg.sender, unsoldAmount); emit CancelLongTermOrder(msg.sender, orderId, sellToken, unsoldAmount, buyToken, purchasedAmount); } ///@notice withdraw proceeds from a long term swap function withdrawProceedsFromLongTermSwap(uint256 orderId) external lock execVirtualOrders returns (bool is_expired, address rewardTkn, uint256 totalReward) { (address proceedToken, uint256 proceeds, bool orderExpired) = longTermOrders.withdrawProceedsFromLongTermSwap(orderId); if (proceedToken == token0) { twammReserve0 -= uint112(proceeds); } else { twammReserve1 -= uint112(proceeds); } // update order. Used for tracking / informational if (orderExpired) longTermOrders.orderMap[orderId].isComplete = true; // transfer to owner of order _safeTransfer(proceedToken, msg.sender, proceeds); emit WithdrawProceedsFromLongTermOrder(msg.sender, orderId, proceedToken, proceeds, orderExpired); return (orderExpired, proceedToken, proceeds); } ///@notice execute virtual orders in the twamm, bring it up to the blockNumber passed in ///updates the TWAP if it is the first amm tx of the block function executeVirtualOrdersInternal(uint256 blockTimestamp) internal { if(newSwapsPaused) return; // skip twamm executions if(twammUpToDate()) return; // save gas LongTermOrdersLib.ExecuteVirtualOrdersResult memory result; result.newReserve0 = reserve0; result.newReserve1 = reserve1; result.newTwammReserve0 = twammReserve0; result.newTwammReserve1 = twammReserve1; longTermOrders.executeVirtualOrdersUntilTimestamp(blockTimestamp, result); twammReserve0 = uint112(result.newTwammReserve0); twammReserve1 = uint112(result.newTwammReserve1); uint112 newReserve0 = uint112(result.newReserve0); uint112 newReserve1 = uint112(result.newReserve1); uint32 _blockTimestamp = uint32(blockTimestamp % 2 ** 32); uint32 timeElapsed; unchecked{ timeElapsed = _blockTimestamp - blockTimestampLast; // overflow is desired } // update reserve0 and reserve1 if ( timeElapsed > 0 && (newReserve0 != reserve0 || newReserve1 != reserve1)) { emit VirtualOrderExecution( _blockTimestamp, result.newReserve0, result.newReserve1, result.newTwammReserve0, result.newTwammReserve1, result.token0Bought, result.token1Bought, result.token0Sold, result.token1Sold, result.expiries ); _update(newReserve0, newReserve1, reserve0, reserve1); } else { reserve0 = newReserve0; reserve1 = newReserve1; } } ///@notice convenience function to execute virtual orders. Note that this already happens ///before most interactions with the AMM function executeVirtualOrders(uint256 blockTimestamp) public override lock { // blockTimestamp is valid require(longTermOrders.lastVirtualOrderTimestamp <= blockTimestamp && blockTimestamp <= block.timestamp); // INVALID TIMESTAMP executeVirtualOrdersInternal(blockTimestamp); } /// --------------------------- /// ------- TWAMM Views ------- /// --------------------------- ///@notice util function for getting the next orderId function getNextOrderID() public override view returns (uint256){ return longTermOrders.orderId; } ///@notice util function for checking if the twamm is up to date function twammUpToDate() public override view returns (bool) { return block.timestamp == longTermOrders.lastVirtualOrderTimestamp; } function getReserveAfterTwamm(uint256 blockTimestamp) public view returns ( uint112 _reserve0, uint112 _reserve1, uint256 lastVirtualOrderTimestamp, uint112 _twammReserve0, uint112 _twammReserve1 ) { lastVirtualOrderTimestamp = longTermOrders.lastVirtualOrderTimestamp; uint112 bal0 = reserve0 + twammReserve0; // save the balance of token0 uint112 bal1 = reserve1 + twammReserve1; // save the balance of token1 LongTermOrdersLib.ExecuteVirtualOrdersResult memory result; result.newReserve0 = reserve0; result.newReserve1 = reserve1; result.newTwammReserve0 = twammReserve0; result.newTwammReserve1 = twammReserve1; longTermOrders.executeVirtualOrdersUntilTimestampView(blockTimestamp, result); _reserve0 = uint112(bal0 - result.newTwammReserve0); _reserve1 = uint112(bal1 - result.newTwammReserve1); _twammReserve0 = uint112(result.newTwammReserve0); _twammReserve1 = uint112(result.newTwammReserve1); } ///@notice returns the current state of the twamm function getTwammState() public override view returns ( uint256 token0Rate, uint256 token1Rate, uint256 lastVirtualOrderTimestamp, uint256 orderTimeInterval_rtn, uint256 rewardFactorPool0, uint256 rewardFactorPool1 ){ token0Rate = longTermOrders.OrderPool0.currentSalesRate; token1Rate = longTermOrders.OrderPool1.currentSalesRate; lastVirtualOrderTimestamp = longTermOrders.lastVirtualOrderTimestamp; orderTimeInterval_rtn = longTermOrders.orderTimeInterval; rewardFactorPool0 = longTermOrders.OrderPool0.rewardFactor; rewardFactorPool1 = longTermOrders.OrderPool1.rewardFactor; } ///@notice returns salesRates ending on this blockTimestamp function getTwammSalesRateEnding(uint256 _blockTimestamp) public override view returns ( uint256 orderPool0SalesRateEnding, uint256 orderPool1SalesRateEnding ){ uint256 lastExpiryTimestamp = _blockTimestamp - (_blockTimestamp % longTermOrders.orderTimeInterval); orderPool0SalesRateEnding = longTermOrders.OrderPool0.salesRateEndingPerTimeInterval[lastExpiryTimestamp]; orderPool1SalesRateEnding = longTermOrders.OrderPool1.salesRateEndingPerTimeInterval[lastExpiryTimestamp]; } ///@notice returns reward factors at this blockTimestamp function getTwammRewardFactor(uint256 _blockTimestamp) public override view returns ( uint256 rewardFactorPool0AtTimestamp, uint256 rewardFactorPool1AtTimestamp ){ uint256 lastExpiryTimestamp = _blockTimestamp - (_blockTimestamp % longTermOrders.orderTimeInterval); rewardFactorPool0AtTimestamp = longTermOrders.OrderPool0.rewardFactorAtTimestamp[lastExpiryTimestamp]; rewardFactorPool1AtTimestamp = longTermOrders.OrderPool1.rewardFactorAtTimestamp[lastExpiryTimestamp]; } ///@notice returns the twamm Order struct function getTwammOrder(uint256 orderId) public override view returns ( uint256 id, uint256 expirationTimestamp, uint256 saleRate, address owner, address sellTokenAddr, address buyTokenAddr ){ require(orderId < longTermOrders.orderId); // INVALID ORDERID LongTermOrdersLib.Order storage order = longTermOrders.orderMap[orderId]; return (order.id, order.expirationTimestamp, order.saleRate, order.owner, order.sellTokenAddr, order.buyTokenAddr); } ///@notice returns the twamm Order withdrawable proceeds // IMPORTANT: Can be stale. Should call executeVirtualOrders first or use getTwammOrderProceeds below. // You can also .call() withdrawProceedsFromLongTermSwap // blockTimestamp should be <= current function getTwammOrderProceedsView(uint256 orderId, uint256 blockTimestamp) public override view returns ( bool orderExpired, uint256 totalReward ){ require(orderId < longTermOrders.orderId); // INVALID ORDERID LongTermOrdersLib.OrderPool storage orderPool = LongTermOrdersLib.getOrderPool(longTermOrders, longTermOrders.orderMap[orderId].sellTokenAddr); (orderExpired, totalReward) = LongTermOrdersLib.orderPoolGetProceeds(orderPool, orderId, blockTimestamp); } ///@notice returns the twamm Order withdrawable proceeds // Need to update the virtual orders first function getTwammOrderProceeds(uint256 orderId) public override returns ( bool orderExpired, uint256 totalReward ){ executeVirtualOrders(block.timestamp); return getTwammOrderProceedsView(orderId, block.timestamp); } /* ========== RESTRICTED FUNCTIONS - Owner only ========== */ // Only callable once function togglePauseNewSwaps() external override onlyOwner { // Pause new swaps require(!newSwapsPaused); newSwapsPaused = true; } }
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"address","name":"sellToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"unsoldAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"buyToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"purchasedAmount","type":"uint256"}],"name":"CancelLongTermOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"numberOfTimeIntervals","type":"uint256"}],"name":"LongTermSwap0To1","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"numberOfTimeIntervals","type":"uint256"}],"name":"LongTermSwap1To0","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1Out","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint112","name":"reserve0","type":"uint112"},{"indexed":false,"internalType":"uint112","name":"reserve1","type":"uint112"}],"name":"Sync","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"blocktimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newReserve0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newReserve1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTwammReserve0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newTwammReserve1","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token0Bought","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token1Bought","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token0Sold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"token1Sold","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"expiries","type":"uint256"}],"name":"VirtualOrderExecution","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"addr","type":"address"},{"indexed":false,"internalType":"uint256","name":"orderId","type":"uint256"},{"indexed":true,"internalType":"address","name":"proceedToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"proceeds","type":"uint256"},{"indexed":false,"internalType":"bool","name":"orderExpired","type":"bool"}],"name":"WithdrawProceedsFromLongTermOrder","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINIMUM_LIQUIDITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"TWAPObservationHistory","outputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"price0CumulativeLast","type":"uint256"},{"internalType":"uint256","name":"price1CumulativeLast","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"burn","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"cancelLongTermSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockTimestamp","type":"uint256"}],"name":"executeVirtualOrders","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"offset","type":"uint256"},{"internalType":"uint256","name":"limit","type":"uint256"}],"name":"getDetailedOrdersForUser","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"expirationTimestamp","type":"uint256"},{"internalType":"uint256","name":"saleRate","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"sellTokenAddr","type":"address"},{"internalType":"address","name":"buyTokenAddr","type":"address"},{"internalType":"bool","name":"isComplete","type":"bool"}],"internalType":"struct LongTermOrdersLib.Order[]","name":"detailed_orders","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNextOrderID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getOrderIDsForUser","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getOrderIDsForUserLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockTimestamp","type":"uint256"}],"name":"getReserveAfterTwamm","outputs":[{"internalType":"uint112","name":"_reserve0","type":"uint112"},{"internalType":"uint112","name":"_reserve1","type":"uint112"},{"internalType":"uint256","name":"lastVirtualOrderTimestamp","type":"uint256"},{"internalType":"uint112","name":"_twammReserve0","type":"uint112"},{"internalType":"uint112","name":"_twammReserve1","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint112","name":"_reserve0","type":"uint112"},{"internalType":"uint112","name":"_reserve1","type":"uint112"},{"internalType":"uint32","name":"_blockTimestampLast","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTWAPHistoryLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"getTwammOrder","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"uint256","name":"expirationTimestamp","type":"uint256"},{"internalType":"uint256","name":"saleRate","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"sellTokenAddr","type":"address"},{"internalType":"address","name":"buyTokenAddr","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"getTwammOrderProceeds","outputs":[{"internalType":"bool","name":"orderExpired","type":"bool"},{"internalType":"uint256","name":"totalReward","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"},{"internalType":"uint256","name":"blockTimestamp","type":"uint256"}],"name":"getTwammOrderProceedsView","outputs":[{"internalType":"bool","name":"orderExpired","type":"bool"},{"internalType":"uint256","name":"totalReward","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTwammReserves","outputs":[{"internalType":"uint112","name":"_reserve0","type":"uint112"},{"internalType":"uint112","name":"_reserve1","type":"uint112"},{"internalType":"uint32","name":"_blockTimestampLast","type":"uint32"},{"internalType":"uint112","name":"_twammReserve0","type":"uint112"},{"internalType":"uint112","name":"_twammReserve1","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockTimestamp","type":"uint256"}],"name":"getTwammRewardFactor","outputs":[{"internalType":"uint256","name":"rewardFactorPool0AtTimestamp","type":"uint256"},{"internalType":"uint256","name":"rewardFactorPool1AtTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_blockTimestamp","type":"uint256"}],"name":"getTwammSalesRateEnding","outputs":[{"internalType":"uint256","name":"orderPool0SalesRateEnding","type":"uint256"},{"internalType":"uint256","name":"orderPool1SalesRateEnding","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTwammState","outputs":[{"internalType":"uint256","name":"token0Rate","type":"uint256"},{"internalType":"uint256","name":"token1Rate","type":"uint256"},{"internalType":"uint256","name":"lastVirtualOrderTimestamp","type":"uint256"},{"internalType":"uint256","name":"orderTimeInterval_rtn","type":"uint256"},{"internalType":"uint256","name":"rewardFactorPool0","type":"uint256"},{"internalType":"uint256","name":"rewardFactorPool1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"kLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0In","type":"uint256"},{"internalType":"uint256","name":"numberOfTimeIntervals","type":"uint256"}],"name":"longTermSwapFrom0To1","outputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount1In","type":"uint256"},{"internalType":"uint256","name":"numberOfTimeIntervals","type":"uint256"}],"name":"longTermSwapFrom1To0","outputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newSwapsPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"orderIDsForUser","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"orderTimeInterval","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"price0CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"price1CumulativeLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"skim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0Out","type":"uint256"},{"internalType":"uint256","name":"amount1Out","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"togglePauseNewSwaps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"twammReserve0","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"twammReserve1","outputs":[{"internalType":"uint112","name":"","type":"uint112"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"twammUpToDate","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"orderId","type":"uint256"}],"name":"withdrawProceedsFromLongTermSwap","outputs":[{"internalType":"bool","name":"is_expired","type":"bool"},{"internalType":"address","name":"rewardTkn","type":"address"},{"internalType":"uint256","name":"totalReward","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6080604052610e10600555600160225534801561001b57600080fd5b50604080518082018252600b81526a467261787377617020563160a81b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527f86218625b976319c763bc8e7046fd038a50daebafa953af7e2f80f37ea1769f5818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c09091019092528151910120600355601b80546001600160a01b031916331790556155a080620001106000396000f3fe608060405234801561001057600080fd5b50600436106103575760003560e01c80637464fc3d116101c85780639610c5f111610104578063c45a0155116100a2578063d505accf1161007c578063d505accf14610a15578063dd62ed3e14610a28578063e852bc2e14610a53578063fff6cae914610a9257600080fd5b8063c45a0155146109c2578063c9738a0d146109e2578063d21220a7146109f557600080fd5b8063a9059cbb116100de578063a9059cbb14610943578063ba9a7a5614610956578063bc25cf771461095f578063bcaa64ea1461097257600080fd5b80639610c5f11461091157806396f2912714610931578063a1462c191461093957600080fd5b80637fa2ee6e11610171578063852a8dbe1161014b578063852a8dbe1461088f57806387353fed146108a257806389afcb44146108c257806395d89b41146108d557600080fd5b80637fa2ee6e1461082f57806381ca79981461083757806381fd0a461461084a57600080fd5b806378dd0298116101a257806378dd0298146107db5780637d316e28146107e35780637ecebe001461080f57600080fd5b80637464fc3d14610794578063748fc63b1461079d578063753bfd4b146107a657600080fd5b80632e0ae37511610297578063485cc955116102405780635909c0d51161021a5780635909c0d5146107515780635a3d5493146107595780636a6278421461076157806370a082311461077457600080fd5b8063485cc955146106cf5780634894c53c146106e25780634adc77c2146106f557600080fd5b80633644e515116102715780633644e5151461068b578063422fff051461069457806343c99081146106bc57600080fd5b80632e0ae3751461063757806330adf81f1461064a578063313ce5671461067157600080fd5b80630ece7236116103045780631fc2fa7f116102de5780631fc2fa7f1461059f57806323b872dd146105cc57806327e73836146105df5780632c8488da1461060d57600080fd5b80630ece72361461053c57806318160ddd146105755780631f4f5b421461058c57600080fd5b8063094cf14911610335578063094cf14914610429578063095ea7b3146104d45780630dfe1681146104f757600080fd5b8063022c0d9f1461035c57806306fdde03146103715780630902f1ac146103c3575b600080fd5b61036f61036a366004614e6d565b610a9a565b005b6103ad6040518060400160405280600b81526020017f467261787377617020563100000000000000000000000000000000000000000081525081565b6040516103ba9190614f33565b60405180910390f35b601e54604080516dffffffffffffffffffffffffffff80841682526e01000000000000000000000000000084041660208201527c010000000000000000000000000000000000000000000000000000000090920463ffffffff16908201526060016103ba565b61048d601e54601a546dffffffffffffffffffffffffffff808316936e0100000000000000000000000000008085048316947c0100000000000000000000000000000000000000000000000000000000900463ffffffff1693838116939190041690565b604080516dffffffffffffffffffffffffffff9687168152948616602086015263ffffffff909316928401929092528316606083015291909116608082015260a0016103ba565b6104e76104e2366004614f84565b6111a2565b60405190151581526020016103ba565b601c546105179073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016103ba565b601a54610556906dffffffffffffffffffffffffffff1681565b6040516dffffffffffffffffffffffffffff90911681526020016103ba565b61057e60005481565b6040519081526020016103ba565b61036f61059a366004614fb0565b6111b8565b601a546104e7907c0100000000000000000000000000000000000000000000000000000000900460ff1681565b6104e76105da366004614fc9565b6113b2565b6105f26105ed366004614fb0565b61148c565b604080519384526020840192909252908201526060016103ba565b61062061061b36600461500a565b6114bf565b6040805192151583526020830191909152016103ba565b61036f610645366004614fb0565b611520565b61057e7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b610679601281565b60405160ff90911681526020016103ba565b61057e60035481565b6106a76106a2366004614fb0565b611560565b604080519283526020830191909152016103ba565b6106a76106ca366004614fb0565b6115a6565b61036f6106dd36600461502c565b6115ec565b6106206106f0366004614fb0565b61168e565b610708610703366004614fb0565b6116ad565b6040805196875260208701959095529385019290925273ffffffffffffffffffffffffffffffffffffffff908116606085015290811660808401521660a082015260c0016103ba565b61057e61171f565b61057e611766565b61057e61076f366004615065565b6117ad565b61057e610782366004615065565b60016020526000908152604090205481565b61057e601f5481565b61057e60055481565b61057e6107b4366004615065565b73ffffffffffffffffffffffffffffffffffffffff16600090815260208052604090205490565b60185461057e565b601a54610556906e01000000000000000000000000000090046dffffffffffffffffffffffffffff1681565b61057e61081d366004615065565b60046020526000908152604090205481565b60215461057e565b61057e61084536600461500a565b611b37565b61085d610858366004614fb0565b611c9d565b60408051931515845273ffffffffffffffffffffffffffffffffffffffff9092166020840152908201526060016103ba565b61057e61089d366004614f84565b611e7e565b6108b56108b0366004615082565b611eae565b6040516103ba91906150b7565b6106a76108d0366004615065565b6120e5565b6103ad6040518060400160405280600581526020017f46532d563100000000000000000000000000000000000000000000000000000081525081565b61092461091f366004615065565b612595565b6040516103ba919061515b565b61036f61260c565b60075442146104e7565b6104e7610951366004614f84565b612738565b61057e6103e881565b61036f61096d366004615065565b612745565b610985610980366004614fb0565b612913565b604080516dffffffffffffffffffffffffffff9687168152948616602086015284019290925283166060830152909116608082015260a0016103ba565b601b546105179073ffffffffffffffffffffffffffffffffffffffff1681565b61057e6109f036600461500a565b612aa7565b601d546105179073ffffffffffffffffffffffffffffffffffffffff1681565b61036f610a2336600461519f565b612be2565b61057e610a3636600461502c565b600260209081526000928352604080842090915290825290205481565b600a54601154600754600654600b54601254604080519687526020870195909552938501929092526060840152608083015260a082015260c0016103ba565b61036f612e13565b602254600114610aa957600080fd5b6000602255610ab742612fda565b6000851180610ac65750600084115b610b37576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303300000000000000000000000000000000000000000000000000000000604082015260600190565b60405180910390fd5b600080610b93601e546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b5091509150816dffffffffffffffffffffffffffff1687108015610bc65750806dffffffffffffffffffffffffffff1686105b610c2e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303400000000000000000000000000000000000000000000000000000000604082015260600190565b601c54601d54600091829173ffffffffffffffffffffffffffffffffffffffff918216919081169089168214801590610c9357508073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614155b610cfb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303500000000000000000000000000000000000000000000000000000000604082015260600190565b8a15610d0c57610d0c828a8d61333e565b8915610d1d57610d1d818a8c61333e565b8615610db0576040517f10d1e85c00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16906310d1e85c90610d7d9033908f908f908e908e90600401615216565b600060405180830381600087803b158015610d9757600080fd5b505af1158015610dab573d6000803e3d6000fd5b505050505b601a546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526dffffffffffffffffffffffffffff9091169073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015610e30573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e54919061528e565b610e5e91906152d6565b601a546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529195506e01000000000000000000000000000090046dffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610ef1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f15919061528e565b610f1f91906152d6565b92505050600089856dffffffffffffffffffffffffffff16610f4191906152d6565b8311610f4e576000610f72565b610f688a6dffffffffffffffffffffffffffff87166152d6565b610f7290846152d6565b90506000610f908a6dffffffffffffffffffffffffffff87166152d6565b8311610f9d576000610fc1565b610fb78a6dffffffffffffffffffffffffffff87166152d6565b610fc190846152d6565b90506000821180610fd25750600081115b61103a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303600000000000000000000000000000000000000000000000000000000604082015260600190565b60006110478360036152ed565b611053866103e86152ed565b61105d91906152d6565b9050600061106c8360036152ed565b611078866103e86152ed565b61108291906152d6565b90506110a16dffffffffffffffffffffffffffff808916908a166152ed565b6110ae90620f42406152ed565b6110b882846152ed565b1015611120576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f4b000000000000000000000000000000000000000000000000000000000000006044820152606401610b2e565b505061112e848488886134e0565b60408051838152602081018390529081018c9052606081018b905273ffffffffffffffffffffffffffffffffffffffff8a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001602255505050505050505050565b60006111af338484613806565b50600192915050565b6022546001146111c757600080fd5b60006022556111d542612fda565b60008080806111e5600686613875565b601c549397509195509350915073ffffffffffffffffffffffffffffffffffffffff80841691161480611218578361121a565b815b601a805460009061123c9084906dffffffffffffffffffffffffffff1661532a565b92506101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff16021790555080611279578161127b565b835b601a8054600e906112af9084906e01000000000000000000000000000090046dffffffffffffffffffffffffffff1661532a565b82546dffffffffffffffffffffffffffff9182166101009390930a928302919092021990911617905550600086815260196020526040902060050180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905561133283338461333e565b61133d85338661333e565b6040805187815273ffffffffffffffffffffffffffffffffffffffff878116602083015291810186905290841660608201526080810183905233907f3c5d5e0947e8b8050cf53e91c7496de2499da1b7613ec86b8fda8705789663909060a00160405180910390a25050600160225550505050565b73ffffffffffffffffffffffffffffffffffffffff831660009081526002602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146114775773ffffffffffffffffffffffffffffffffffffffff841660009081526002602090815260408083203384529091529020546114459083906152d6565b73ffffffffffffffffffffffffffffffffffffffff851660009081526002602090815260408083203384529091529020555b611482848484613916565b5060019392505050565b6021818154811061149c57600080fd5b600091825260209091206003909102018054600182015460029092015490925083565b60008060066012015484106114d357600080fd5b6000848152601960205260408120600401546115079060069073ffffffffffffffffffffffffffffffffffffffff166139e5565b9050611514818686613a21565b90969095509350505050565b60225460011461152f57600080fd5b600060225560075481108015906115465750428111155b61154f57600080fd5b61155881612fda565b506001602255565b6000806000600660000154846115769190615388565b61158090856152d6565b6000908152600c6020908152604080832054601390925290912054909590945092505050565b6000806000600660000154846115bc9190615388565b6115c690856152d6565b600090815260106020908152604080832054601790925290912054909590945092505050565b601b5473ffffffffffffffffffffffffffffffffffffffff16331461161057600080fd5b601c80547fffffffffffffffffffffffff000000000000000000000000000000000000000090811673ffffffffffffffffffffffffffffffffffffffff858116918217909355601d805483169385169384179055600554600880548416909217909155600980549092169092179055426007556006555050565b5050565b60008061169a42611520565b6116a483426114bf565b91509150915091565b60008060008060008060066012015487106116c757600080fd5b50505060009384525050601960205250604090208054600182015460028301546003840154600485015460059095015493959294919373ffffffffffffffffffffffffffffffffffffffff9182169392821692911690565b60215460009061172f5750600090565b6021805461173f906001906152d6565b8154811061174f5761174f61539c565b906000526020600020906003020160010154905090565b6021546000906117765750600090565b60218054611786906001906152d6565b815481106117965761179661539c565b906000526020600020906003020160020154905090565b60006022546001146117be57600080fd5b60006022556117cc42612fda565b600080611828601e546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50601a54601c546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529395509193506000926dffffffffffffffffffffffffffff9091169173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa1580156118b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118d8919061528e565b6118e291906152d6565b601a54601d546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529293506000926e0100000000000000000000000000009092046dffffffffffffffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561197d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119a1919061528e565b6119ab91906152d6565b905060006119c96dffffffffffffffffffffffffffff8616846152d6565b905060006119e76dffffffffffffffffffffffffffff8616846152d6565b905060006119f58787613af8565b60008054919250819003611a36576103e8611a18611a1385876152ed565b613c65565b611a2291906152d6565b9850611a3160006103e8613cd5565b611a8b565b611a886dffffffffffffffffffffffffffff8916611a5483876152ed565b611a5e91906153cb565b6dffffffffffffffffffffffffffff8916611a7984876152ed565b611a8391906153cb565b613d80565b98505b60008911611a9857600080fd5b611aa28a8a613cd5565b611aae86868a8a6134e0565b8115611ae957601e54611ae5906dffffffffffffffffffffffffffff6e0100000000000000000000000000008204811691166152ed565b601f555b604080518581526020810185905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a25050600160225550949695505050505050565b6000602254600114611b4857600080fd5b6000602255601a547c0100000000000000000000000000000000000000000000000000000000900460ff1615611b7d57600080fd5b611b8642612fda565b6000611b9184613d96565b905080601a600e8282829054906101000a90046dffffffffffffffffffffffffffff16611bbe91906153df565b82546101009290920a6dffffffffffffffffffffffffffff818102199093169183160217909155601a54601e54919250611c12916e0100000000000000000000000000009182900484169190048316615411565b1115611c1d57600080fd5b611c2960068285613ef2565b336000818152602080805260408083208054600181018255908452928290209092018490558151848152908101859052908101869052919350907fe1ce07267c05b1609d3bd4046ca369b74e64cd2b45ee8321ccc79783252c60b4906060015b60405180910390a250600160225592915050565b6000806000602254600114611cb157600080fd5b6000602255611cbf42612fda565b60008080611cce600688613f2e565b601c54929550909350915073ffffffffffffffffffffffffffffffffffffffff90811690841603611d5557601a8054839190600090611d1e9084906dffffffffffffffffffffffffffff1661532a565b92506101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff160217905550611db3565b81601a600e8282829054906101000a90046dffffffffffffffffffffffffffff16611d80919061532a565b92506101000a8154816dffffffffffffffffffffffffffff02191690836dffffffffffffffffffffffffffff1602179055505b8015611e0857600087815260196020526040902060050180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790555b611e1383338461333e565b604080518881526020810184905282151581830152905173ffffffffffffffffffffffffffffffffffffffff85169133917f43168622ddb54ed84ccad30626ace7077235dc531c67aaf639752c45195354489181900360600190a36001602255969195509350915050565b602080528160005260406000208181548110611e9957600080fd5b90600052602060002001600091509150505481565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260208080526040808320805482518185028101850190935280835260609493830182828015611f1857602002820191906000526020600020905b815481526020019060010190808311611f04575b505050505090506000848251611f2e91906152d6565b90506000611f3c8583613d80565b90508067ffffffffffffffff811115611f5757611f57615429565b604051908082528060200260200182016040528015611fdc57816020015b6040805160e08101825260008082526020808301829052928201819052606082018190526080820181905260a0820181905260c082015282527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff909201910181611f755790505b50935060005b818110156120da576019600085611ff9848b615411565b815181106120095761200961539c565b6020908102919091018101518252818101929092526040908101600020815160e08101835281548152600182015493810193909352600281015491830191909152600381015473ffffffffffffffffffffffffffffffffffffffff908116606084015260048201548116608084015260059091015490811660a083015274010000000000000000000000000000000000000000900460ff16151560c082015285518690839081106120bc576120bc61539c565b602002602001018190525080806120d290615458565b915050611fe2565b505050509392505050565b6000806022546001146120f757600080fd5b600060225561210542612fda565b600080612161601e546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50601c54601d54601a546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015294965092945073ffffffffffffffffffffffffffffffffffffffff918216939116916000916dffffffffffffffffffffffffffff9091169084906370a0823190602401602060405180830381865afa1580156121f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221b919061528e565b61222591906152d6565b601a546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529192506000916e0100000000000000000000000000009091046dffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff8516906370a0823190602401602060405180830381865afa1580156122bc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122e0919061528e565b6122ea91906152d6565b306000908152600160205260408120549192506123078888613af8565b6000549091508061231886856152ed565b61232291906153cb565b9a508061232f85856152ed565b61233991906153cb565b995060008b11801561234b575060008a115b61235457600080fd5b61235e3084613fc5565b612369878d8d61333e565b612374868d8c61333e565b601a546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526dffffffffffffffffffffffffffff9091169073ffffffffffffffffffffffffffffffffffffffff8916906370a0823190602401602060405180830381865afa1580156123f4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612418919061528e565b61242291906152d6565b601a546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529196506e01000000000000000000000000000090046dffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff8816906370a0823190602401602060405180830381865afa1580156124b5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124d9919061528e565b6124e391906152d6565b93506124f185858b8b6134e0565b811561252c57601e54612528906dffffffffffffffffffffffffffff6e0100000000000000000000000000008204811691166152ed565b601f555b604080518c8152602081018c905273ffffffffffffffffffffffffffffffffffffffff8e169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050505050505050506001602281905550915091565b73ffffffffffffffffffffffffffffffffffffffff81166000908152602080805260409182902080548351818402810184019094528084526060939283018282801561260057602002820191906000526020600020905b8154815260200190600101908083116125ec575b50505050509050919050565b601b54604080517f094b74150000000000000000000000000000000000000000000000000000000081529051339273ffffffffffffffffffffffffffffffffffffffff169163094b74159160048083019260209291908290030181865afa15801561267b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269f9190615490565b73ffffffffffffffffffffffffffffffffffffffff16146126bf57600080fd5b601a547c0100000000000000000000000000000000000000000000000000000000900460ff16156126ef57600080fd5b601a80547fffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffff167c0100000000000000000000000000000000000000000000000000000000179055565b60006111af338484613916565b60225460011461275457600080fd5b600060225561276242612fda565b601c54601d54601a54601e5473ffffffffffffffffffffffffffffffffffffffff938416939092169161286291849186916127b0916dffffffffffffffffffffffffffff91821691166153df565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526dffffffffffffffffffffffffffff919091169073ffffffffffffffffffffffffffffffffffffffff8716906370a08231906024015b602060405180830381865afa15801561282f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612853919061528e565b61285d91906152d6565b61333e565b601a54601e5461290991839186916128a3916dffffffffffffffffffffffffffff6e01000000000000000000000000000092839004811692909104166153df565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526dffffffffffffffffffffffffffff919091169073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401612812565b5050600160225550565b600754601a54601e5460009283929091839182918291612946916dffffffffffffffffffffffffffff91821691166153df565b601a54601e54919250600091612986916dffffffffffffffffffffffffffff6e0100000000000000000000000000009182900481169291909104166153df565b90506129f760405180610120016040528060006dffffffffffffffffffffffffffff16815260200160006dffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b601e546dffffffffffffffffffffffffffff80821683526e0100000000000000000000000000009182900481166020840152601a54808216604085015291909104166060820152612a4a60068a83614078565b6040810151612a69906dffffffffffffffffffffffffffff85166152d6565b97508060600151826dffffffffffffffffffffffffffff16612a8b91906152d6565b9650806040015194508060600151935050505091939590929450565b6000602254600114612ab857600080fd5b6000602255601a547c0100000000000000000000000000000000000000000000000000000000900460ff1615612aed57600080fd5b612af642612fda565b6000612b01846141fc565b601a80549192508291600090612b289084906dffffffffffffffffffffffffffff166153df565b82546101009290920a6dffffffffffffffffffffffffffff818102199093169183160217909155601a54601e54919250612b6791908316908316615411565b1115612b7257600080fd5b612b7e60068285614311565b336000818152602080805260408083208054600181018255908452928290209092018490558151848152908101859052908101869052919350907f9971294258b76b481032b9c1f7f5594619d7cf40e29e224de9e71481bd0a4f8590606001611c89565b42841015612bef57600080fd5b60035473ffffffffffffffffffffffffffffffffffffffff8816600090815260046020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b919087612c4f83615458565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001612cf09291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015612d79573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590612df457508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b612dfd57600080fd5b612e08898989613806565b505050505050505050565b602254600114612e2257600080fd5b6000602255612e3042612fda565b601a54601c546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152612fd3926dffffffffffffffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015612eb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ed8919061528e565b612ee291906152d6565b601a54601d546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526e0100000000000000000000000000009092046dffffffffffffffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015612f77573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9b919061528e565b612fa591906152d6565b601e546dffffffffffffffffffffffffffff808216916e0100000000000000000000000000009004166134e0565b6001602255565b601a547c0100000000000000000000000000000000000000000000000000000000900460ff16156130085750565b60075442036130145750565b61308360405180610120016040528060006dffffffffffffffffffffffffffff16815260200160006dffffffffffffffffffffffffffff168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b601e546dffffffffffffffffffffffffffff80821683526e0100000000000000000000000000009182900481166020840152601a548082166040850152919091041660608201526130d660068383614345565b6040810151601a805460608401516dffffffffffffffffffffffffffff9081166e010000000000000000000000000000027fffffffff0000000000000000000000000000000000000000000000000000000090921693169290921791909117905580516020820151600061314f64010000000086615388565b601e5490915063ffffffff7c010000000000000000000000000000000000000000000000000000000090910481168203908116158015906131d65750601e546dffffffffffffffffffffffffffff85811691161415806131d65750601e546dffffffffffffffffffffffffffff8481166e0100000000000000000000000000009092041614155b156132e3577f793ee8b0d8020fc042a920607e3cbd37f5132c011786c8dd10a685f4414ed3818286600001518760200151886040015189606001518a608001518b60a001518c60c001518d60e001518e610100015160405161329c9a9998979695949392919063ffffffff9a909a168a526dffffffffffffffffffffffffffff98891660208b01529690971660408901526060880194909452608087019290925260a086015260c085015260e08401526101008301919091526101208201526101400190565b60405180910390a1601e546132de906dffffffffffffffffffffffffffff8087169186821691818116916e0100000000000000000000000000009004166134e0565b613336565b601e80546dffffffffffffffffffffffffffff8581166e010000000000000000000000000000027fffffffff00000000000000000000000000000000000000000000000000000000909216908716171790555b505050505050565b604080518082018252601981527f7472616e7366657228616464726573732c75696e743235362900000000000000602091820152815173ffffffffffffffffffffffffffffffffffffffff85811660248301526044808301869052845180840390910181526064909201845291810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839287169161340591906154ad565b6000604051808303816000865af19150503d8060008114613442576040519150601f19603f3d011682016040523d82523d6000602084013e613447565b606091505b509150915081801561347157508051158061347157508080602001905181019061347191906154c9565b6134d9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303100000000000000000000000000000000000000000000000000000000604082015260600190565b5050505050565b601a546dffffffffffffffffffffffffffff906134ff90821686615411565b1115801561353c5750601a546dffffffffffffffffffffffffffff90613539906e0100000000000000000000000000009004821685615411565b11155b6135a4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610b2e9060208082526004908201527f4543303200000000000000000000000000000000000000000000000000000000604082015260600190565b60006135b564010000000042615388565b601e5490915063ffffffff7c0100000000000000000000000000000000000000000000000000000000909104811682039081161580159061360557506dffffffffffffffffffffffffffff841615155b801561362057506dffffffffffffffffffffffffffff831615155b1561371657602160405180606001604052808463ffffffff1681526020018363ffffffff1661367688613652896144ec565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff169061451d565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff160261369d61171f565b0181526020018363ffffffff166136b7876136528a6144ec565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff16026136de611766565b019052815460018181018455600093845260209384902083516003909302019182559282015192810192909255604001516002909101555b601e805463ffffffff84167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff8981166e0100000000000000000000000000009081027fffffffff000000000000000000000000000000000000000000000000000000009095168c83161794909417918216831794859055604080519382169282169290921783529290930490911660208201527f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a1505050505050565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600081815260138301602052604081206005810154600482015473ffffffffffffffffffffffffffffffffffffffff90811693929116908290816138b988876139e5565b90506138ca81888a60010154614539565b6003840154919650935073ffffffffffffffffffffffffffffffffffffffff1633148015613902575060008511806139025750600083115b61390b57600080fd5b505092959194509250565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160205260409020546139479082906152d6565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600160205260408082209390935590841681522054613984908290615411565b73ffffffffffffffffffffffffffffffffffffffff80841660008181526001602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906138689085815260200190565b600282015460009073ffffffffffffffffffffffffffffffffffffffff838116911614613a155782600b01613a1a565b826004015b9392505050565b6000828152600484016020526040812054819080613a3e57600080fd5b600085815260038701602090815260408083205460058a019092529091205481861115613a9d5760008281526006890160205260409020546e010000000000000000000000000000620f42408383038602040494506001955050613aed565b6e010000000000000000000000000000620f42406dffffffffffffffffffffffffffff1684838b60010154030281613ad757613ad7615359565b0481613ae557613ae5615359565b049350600094505b505050935093915050565b600080601b60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663017e7e586040518163ffffffff1660e01b8152600401602060405180830381865afa158015613b68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b8c9190615490565b601f5473ffffffffffffffffffffffffffffffffffffffff8216158015945091925090613c51578015613c4c576000613bdb611a136dffffffffffffffffffffffffffff8088169089166152ed565b90506000613be883613c65565b905080821115613c49576000613bfe82846152d6565b600054613c0b91906152ed565b9050600082613c1b8560056152ed565b613c259190615411565b90506000613c3382846153cb565b90508015613c4557613c458782613cd5565b5050505b50505b613c5d565b8015613c5d576000601f555b505092915050565b60006003821115613cc65750806000613c7f6002836153cb565b613c8a906001615411565b90505b81811015613cc057905080600281613ca581866153cb565b613caf9190615411565b613cb991906153cb565b9050613c8d565b50919050565b8115613cd0575060015b919050565b80600054613ce39190615411565b600090815573ffffffffffffffffffffffffffffffffffffffff8316815260016020526040902054613d16908290615411565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600160205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90613d749085815260200190565b60405180910390a35050565b6000818310613d8f5781613a1a565b5090919050565b601d546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600091829173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa158015613e09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e2d919061528e565b601d54909150613e559073ffffffffffffffffffffffffffffffffffffffff1633308661462b565b601d546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152829173ffffffffffffffffffffffffffffffffffffffff16906370a08231906024015b602060405180830381865afa158015613ec4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ee8919061528e565b613a1a91906152d6565b60038301546002840154600091613f2691869173ffffffffffffffffffffffffffffffffffffffff908116911686866147c2565b949350505050565b600081815260138301602052604081206005810154600482015473ffffffffffffffffffffffffffffffffffffffff9182169392839290918391613f74918991166139e5565b9050613f8581878960010154614a2a565b6003840154919550935073ffffffffffffffffffffffffffffffffffffffff1633148015613fb35750600084115b613fbc57600080fd5b50509250925092565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260016020526040902054613ff69082906152d6565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160205260408120919091555461402b9082906152d6565b600090815560405182815273ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001613d74565b6001830154835460008161408c8185615388565b61409690856152d6565b6140a09190615411565b600487018054600b8901805493945091925b888510156141925760008581526002850160205260409020541515806140e75750600085815260028401602052604090205415155b156141815760006140f888876152d6565b90506000620f424061410a83866152ed565b61411491906153cb565b90506000620f424061412684866152ed565b61413091906153cb565b905061413d8b8383614a77565b5050600088815260028801602052604090205461415a90866152d6565b600089815260028801602052604090205490955061417890856152d6565b93508799505050505b61418b8686615411565b94506140b2565b8887146141f05760006141a5888b6152d6565b90506000620f42406141b783866152ed565b6141c191906153cb565b90506000620f42406141d384866152ed565b6141dd91906153cb565b90506141ea8b8383614a77565b50505050505b50505050505050505050565b601c546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152600091829173ffffffffffffffffffffffffffffffffffffffff909116906370a0823190602401602060405180830381865afa15801561426f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190614293919061528e565b601c549091506142bb9073ffffffffffffffffffffffffffffffffffffffff1633308661462b565b601c546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152829173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401613ea7565b60028301546003840154600091613f2691869173ffffffffffffffffffffffffffffffffffffffff908116911686866147c2565b600183015483546000816143598185615388565b61436390856152d6565b61436d9190615411565b905060048601600b87015b868310156144585760008381526002830160205260409020541515806143ad5750600083815260028201602052604090205415155b156144475760006143be86856152d6565b8354909150600090620f4240906143d69084906152ed565b6143e091906153cb565b8354909150600090620f4240906143f89085906152ed565b61440291906153cb565b90506000806144128b8585614a77565b915091506144208782614c0c565b61442a8683614c0c565b6144348789614c49565b61443e8689614c49565b87995050505050505b6144518484615411565b9250614378565b8685146144dd57600061446b86896152d6565b8354909150600090620f4240906144839084906152ed565b61448d91906153cb565b8354909150600090620f4240906144a59085906152ed565b6144af91906153cb565b90506000806144bf8b8585614a77565b915091506144cd8782614c0c565b6144d78683614c0c565b50505050505b50505050506001929092015550565b60006145176e0100000000000000000000000000006dffffffffffffffffffffffffffff84166154eb565b92915050565b6000613a1a6dffffffffffffffffffffffffffff83168461552f565b6000828152600384016020526040812054819083811161455857600080fd5b6000858152600487016020526040902054620f42408161457887856152d6565b61458291906152ed565b61458c91906153cb565b600087815260058901602052604090205460018901549195506e01000000000000000000000000000091620f4240919003830204049250808760000160008282546145d791906152d6565b90915550506000868152600488016020908152604080832083905560038a01825280832083905584835260028a019091528120805483929061461a9084906152d6565b925050819055505050935093915050565b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd0000000000000000000000000000000000000000000000000000000017905291516000928392908816916146ca91906154ad565b6000604051808303816000865af19150503d8060008114614707576040519150601f19603f3d011682016040523d82523d6000602084013e61470c565b606091505b509150915081801561473657508051158061473657508080602001905181019061473691906154c9565b613336576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c65640000000000000000000000000000006064820152608401610b2e565b8454600090429082906147d59083615388565b6147df90836152d6565b90506000816147ef866001615411565b8a546147fb91906152ed565b6148059190615411565b9050600061481384836152d6565b61482088620f42406152ed565b61482a91906153cb565b90506000811161483957600080fd5b60006148458b8b6139e5565b9050614857818c601201548486614c89565b6040518060e001604052808c6012015481526020018481526020018381526020013373ffffffffffffffffffffffffffffffffffffffff1681526020018b73ffffffffffffffffffffffffffffffffffffffff1681526020018a73ffffffffffffffffffffffffffffffffffffffff168152602001600015158152508b60130160008d60120154815260200190815260200160002060008201518160000155602082015181600101556040820151816002015560608201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060808201518160040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060a08201518160050160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060c08201518160050160146101000a81548160ff0219169083151502179055509050508a6012016000815480929190614a1790615458565b909155509b9a5050505050505050505050565b600080614a38858585613a21565b925090508015614a58576000848152600486016020526040812055614a6f565b600185015460008581526005870160205260409020555b935093915050565b6000806000856040015186600001516dffffffffffffffffffffffffffff16614aa09190615411565b90506000866060015187602001516dffffffffffffffffffffffffffff16614ac89190615411565b9050614afe87600001516dffffffffffffffffffffffffffff1688602001516dffffffffffffffffffffffffffff168888614cfd565b604089015191955093508690614b15908690615411565b614b1f91906152d6565b604088015260608701518590614b36908590615411565b614b4091906152d6565b60608801526040870151614b5490836152d6565b6dffffffffffffffffffffffffffff1687526060870151614b7590826152d6565b6dffffffffffffffffffffffffffff166020880152608087018051859190614b9e908390615411565b90525060a087018051849190614bb5908390615411565b90525060c087018051879190614bcc908390615411565b90525060e087018051869190614be3908390615411565b9052506101008701805160019190614bfc908390615411565b9052509296919550909350505050565b81541561168a578154700f42400000000000000000000000000000820281614c3657614c36615359565b6001939093018054919093040190915550565b6000818152600283016020526040812054835490918491614c6b9084906152d6565b90915550506001820154600091825260069092016020526040902055565b81846000016000828254614c9d9190615411565b9091555050600184015460008481526005860160209081526040808320939093556003870181528282208490556004870181528282208590558382526002870190529081208054849290614cf2908490615411565b909155505050505050565b60008060018411801590614d12575060018311155b614e3f5760018411614d61576000614d2c846103e56152ed565b905080614d3b876103e86152ed565b614d459190615411565b614d4f82896152ed565b614d5991906153cb565b925050614e3f565b60018311614dac576000614d77856103e56152ed565b905080614d86886103e86152ed565b614d909190615411565b614d9a82886152ed565b614da491906153cb565b915050614e3f565b60006103e8614dbd866103e56152ed565b614dc791906153cb565b614dd19088615411565b905060006103e8614de4866103e56152ed565b614dee91906153cb565b614df89088615411565b905080614e0583896152ed565b614e0f91906153cb565b614e1990836152d6565b935081614e26828a6152ed565b614e3091906153cb565b614e3a90826152d6565b925050505b94509492505050565b73ffffffffffffffffffffffffffffffffffffffff81168114614e6a57600080fd5b50565b600080600080600060808688031215614e8557600080fd5b85359450602086013593506040860135614e9e81614e48565b9250606086013567ffffffffffffffff80821115614ebb57600080fd5b818801915088601f830112614ecf57600080fd5b813581811115614ede57600080fd5b896020828501011115614ef057600080fd5b9699959850939650602001949392505050565b60005b83811015614f1e578181015183820152602001614f06565b83811115614f2d576000848401525b50505050565b6020815260008251806020840152614f52816040850160208701614f03565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008060408385031215614f9757600080fd5b8235614fa281614e48565b946020939093013593505050565b600060208284031215614fc257600080fd5b5035919050565b600080600060608486031215614fde57600080fd5b8335614fe981614e48565b92506020840135614ff981614e48565b929592945050506040919091013590565b6000806040838503121561501d57600080fd5b50508035926020909101359150565b6000806040838503121561503f57600080fd5b823561504a81614e48565b9150602083013561505a81614e48565b809150509250929050565b60006020828403121561507757600080fd5b8135613a1a81614e48565b60008060006060848603121561509757600080fd5b83356150a281614e48565b95602085013595506040909401359392505050565b602080825282518282018190526000919060409081850190868401855b8281101561514e578151805185528681015187860152858101518686015260608082015173ffffffffffffffffffffffffffffffffffffffff9081169187019190915260808083015182169087015260a0808301519091169086015260c09081015115159085015260e090930192908501906001016150d4565b5091979650505050505050565b6020808252825182820181905260009190848201906040850190845b8181101561519357835183529284019291840191600101615177565b50909695505050505050565b600080600080600080600060e0888a0312156151ba57600080fd5b87356151c581614e48565b965060208801356151d581614e48565b95506040880135945060608801359350608088013560ff811681146151f957600080fd5b9699959850939692959460a0840135945060c09093013592915050565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101949350505050565b6000602082840312156152a057600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156152e8576152e86152a7565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0483118215151615615325576153256152a7565b500290565b60006dffffffffffffffffffffffffffff83811690831681811015615351576153516152a7565b039392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60008261539757615397615359565b500690565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000826153da576153da615359565b500490565b60006dffffffffffffffffffffffffffff808316818516808303821115615408576154086152a7565b01949350505050565b60008219821115615424576154246152a7565b500190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203615489576154896152a7565b5060010190565b6000602082840312156154a257600080fd5b8151613a1a81614e48565b600082516154bf818460208701614f03565b9190910192915050565b6000602082840312156154db57600080fd5b81518015158114613a1a57600080fd5b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff80831681851681830481118215151615615526576155266152a7565b02949350505050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8084168061555e5761555e615359565b9216919091049291505056fea2646970667358221220bdc5b014c6704437df24db228c555db8616bb6648c9811f54a9e45271265b6f564736f6c634300080d0033
Deployed ByteCode Sourcemap
43169:27045:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55114:1958;;;;;;:::i;:::-;;:::i;:::-;;7994:52;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;48564:185;48702:8;;48564:185;;;48702:8;;;;2000:34:1;;48712:8:0;;;;2065:2:1;2050:18;;2043:43;48722:18:0;;;;;;2102::1;;;2095:51;1939:2;1924:18;48564:185:0;1751:401:1;48757:268:0;;48948:8;;48988:13;;48948:8;;;;;48958;;;;;;;48968:18;;;;;;48988:13;;;;49003;;;;;48757:268;;;;;2424:30:1;2481:15;;;2463:34;;2533:15;;;2528:2;2513:18;;2506:43;2597:10;2585:23;;;2565:18;;;2558:51;;;;2645:15;;2640:2;2625:18;;2618:43;2698:15;;;;2692:3;2677:19;;2670:44;2401:3;2386:19;48757:268:0;2157:563:1;9899:156:0;;;;;;:::i;:::-;;:::i;:::-;;;3210:14:1;;3203:22;3185:41;;3173:2;3158:18;9899:156:0;3045:187:1;46214:30:0;;;;;;;;;;;;3413:42:1;3401:55;;;3383:74;;3371:2;3356:18;46214:30:0;3237:226:1;43831:28:0;;;;;;;;;;;;3644:30:1;3632:43;;;3614:62;;3602:2;3587:18;43831:28:0;3468:214:1;8159:33:0;;;;;;;;;3833:25:1;;;3821:2;3806:18;8159:33:0;3687:177:1;60498:829:0;;;;;;:::i;:::-;;:::i;43903:26::-;;;;;;;;;;;;10219:313;;;;;;:::i;:::-;;:::i;46785:47::-;;;;;;:::i;:::-;;:::i;:::-;;;;4717:25:1;;;4773:2;4758:18;;4751:34;;;;4801:18;;;4794:34;4705:2;4690:18;46785:47:0;4515:319:1;69046:517:0;;;;;;:::i;:::-;;:::i;:::-;;;;5285:14:1;;5278:22;5260:41;;5332:2;5317:18;;5310:34;;;;5233:18;69046:517:0;5092:258:1;64303:310:0;;;;;;:::i;:::-;;:::i;8487:117::-;;8538:66;8487:117;;8108:44;;8150:2;8108:44;;;;;5709:4:1;5697:17;;;5679:36;;5667:2;5652:18;8108:44:0;5537:184:1;8335:40:0;;;;;;67040:533;;;;;;:::i;:::-;;:::i;:::-;;;;5900:25:1;;;5956:2;5941:18;;5934:34;;;;5873:18;67040:533:0;5726:248:1;67643:528:0;;;;;;:::i;:::-;;:::i;49522:327::-;;;;;;:::i;:::-;;:::i;69681:262::-;;;;;;:::i;:::-;;:::i;68226:536::-;;;;;;:::i;:::-;;:::i;:::-;;;;6659:25:1;;;6715:2;6700:18;;6693:34;;;;6743:18;;;6736:34;;;;6789:42;6867:15;;;6862:2;6847:18;;6840:43;6920:15;;;6914:3;6899:19;;6892:44;6973:15;6967:3;6952:19;;6945:44;6646:3;6631:19;68226:536:0;6372:623:1;46975:211:0;;;:::i;47192:::-;;;:::i;52135:1272::-;;;;;;:::i;:::-;;:::i;8199:50::-;;;;;;:::i;:::-;;;;;;;;;;;;;;46585:26;;;;;;43660:39;;;;;;47842:134;;;;;;:::i;:::-;47940:21;;47913:7;47940:21;;;:15;:21;;;;;:28;;47842:134;64793:112;64875:22;;64793:112;;43866:28;;;;;;;;;;;;8611:47;;;;;;:::i;:::-;;;;;;;;;;;;;;47409:122;47494:22;:29;47409:122;;59867:567;;;;;;:::i;:::-;;:::i;61391:870::-;;;;;;:::i;:::-;;:::i;:::-;;;;7473:14:1;;7466:22;7448:41;;7537:42;7525:55;;;7520:2;7505:18;;7498:83;7597:18;;;7590:34;7436:2;7421:18;61391:870:0;7252:378:1;46724:52:0;;;;;;:::i;:::-;;:::i;47984:572::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;53519:1483::-;;;;;;:::i;:::-;;:::i;8053:48::-;;;;;;;;;;;;;;;;;;;;;47704:130;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;70049:162::-;;;:::i;64983:146::-;65081:40;;65062:15;:59;64983:146;;10063:148;;;;;;:::i;:::-;;:::i;46015:57::-;;46065:7;46015:57;;57121:395;;;;;;:::i;:::-;;:::i;65137:1068::-;;;;;;:::i;:::-;;:::i;:::-;;;;10246:30:1;10303:15;;;10285:34;;10355:15;;;10350:2;10335:18;;10328:43;10387:18;;10380:34;;;;10450:15;;10445:2;10430:18;;10423:43;10503:15;;;10497:3;10482:19;;10475:44;10223:3;10208:19;65137:1068:0;9977:548:1;46176:31:0;;;;;;;;;59075:567;;;;;;:::i;:::-;;:::i;46251:30::-;;;;;;;;;10540:661;;;;;;:::i;:::-;;:::i;8256:70::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;66268:699;66567:25;:42;66633:25;:42;66714:40;;66567:14;66789:32;66633:25;66852:38;66921;;66268:699;;;11651:25:1;;;11707:2;11692:18;;11685:34;;;;11735:18;;;11728:34;;;;11793:2;11778:18;;11771:34;11836:3;11821:19;;11814:35;11880:3;11865:19;;11858:35;11638:3;11623:19;66268:699:0;11364:535:1;57565:271:0;;;:::i;55114:1958::-;47606:8;;47618:1;47606:13;47598:22;;;;;;47652:1;47641:8;:12;43978:45:::1;44007:15;43978:28;:45::i;:::-;55268:1:::2;55255:10;:14;:32;;;;55286:1;55273:10;:14;55255:32;55247:49;;;;;;;;;;;12106:2:1::0;12088:21;;;12145:1;12125:18;;;12118:29;12183:6;12178:2;12163:18;;12156:34;12222:2;12207:18;;11904:327;55247:49:0::2;;;;;;;;;55338:17;55357::::0;55379:13:::2;48702:8:::0;;;;;;;48712;;;;;;;48722:18;;;;;;;48564:185;55379:13:::2;55337:55;;;;;55439:9;55426:22;;:10;:22;:48;;;;;55465:9;55452:22;;:10;:22;55426:48;55418:65;;;;;;;;;;;12438:2:1::0;12420:21;;;12477:1;12457:18;;;12450:29;12515:6;12510:2;12495:18;;12488:34;12554:2;12539:18;;12236:327;55418:65:0::2;55657:6;::::0;55696::::2;::::0;55522:13:::2;::::0;;;55657:6:::2;::::0;;::::2;::::0;55696;;::::2;::::0;55725:13;::::2;::::0;::::2;::::0;::::2;::::0;:30:::2;;;55748:7;55742:13;;:2;:13;;;;55725:30;55717:47;;;;;;;;;;;12770:2:1::0;12752:21;;;12809:1;12789:18;;;12782:29;12847:6;12842:2;12827:18;;12820:34;12886:2;12871:18;;12568:327;55717:47:0::2;55797:14:::0;;55793:58:::2;;55813:38;55827:7;55836:2;55840:10;55813:13;:38::i;:::-;55904:14:::0;;55900:58:::2;;55920:38;55934:7;55943:2;55947:10;55920:13;:38::i;:::-;56011:15:::0;;56007:99:::2;;56028:78;::::0;;;;:36:::2;::::0;::::2;::::0;::::2;::::0;:78:::2;::::0;56065:10:::2;::::0;56077;;56089;;56101:4;;;;56028:78:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;::::0;::::2;;;;;;;;;56007:99;56177:13;::::0;56132:42:::2;::::0;;;;56168:4:::2;56132:42;::::0;::::2;3383:74:1::0;56177:13:0::2;::::0;;::::2;::::0;56132:27:::2;::::0;::::2;::::0;::::2;::::0;3356:18:1;;56132:42:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:58;;;;:::i;:::-;56261:13;::::0;56216:42:::2;::::0;;;;56252:4:::2;56216:42;::::0;::::2;3383:74:1::0;56121:69:0;;-1:-1:-1;56261:13:0;;::::2;;;::::0;56216:27:::2;::::0;::::2;::::0;::::2;::::0;3356:18:1;;56216:42:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:58;;;;:::i;:::-;56205:69;;55570:716;;56296:14;56336:10;56324:9;:22;;;;;;:::i;:::-;56313:8;:33;:75;;56387:1;56313:75;;;56361:22;56373:10:::0;56361:22:::2;::::0;::::2;;:::i;:::-;56349:35;::::0;:8;:35:::2;:::i;:::-;56296:92:::0;-1:-1:-1;56399:14:0::2;56427:22;56439:10:::0;56427:22:::2;::::0;::::2;;:::i;:::-;56416:8;:33;:75;;56490:1;56416:75;;;56464:22;56476:10:::0;56464:22:::2;::::0;::::2;;:::i;:::-;56452:35;::::0;:8;:35:::2;:::i;:::-;56399:92;;56522:1;56510:9;:13;:30;;;;56539:1;56527:9;:13;56510:30;56502:47;;;;;;;;;;;14329:2:1::0;14311:21;;;14368:1;14348:18;;;14341:29;14406:6;14401:2;14386:18;;14379:34;14445:2;14430:18;;14127:327;56502:47:0::2;56667:21;56712:13;:9:::0;56724:1:::2;56712:13;:::i;:::-;56692:15;:8:::0;56703:4:::2;56692:15;:::i;:::-;56691:35;;;;:::i;:::-;56667:59:::0;-1:-1:-1;56741:21:0::2;56786:13;:9:::0;56798:1:::2;56786:13;:::i;:::-;56766:15;:8:::0;56777:4:::2;56766:15;:::i;:::-;56765:35;;;;:::i;:::-;56741:59:::0;-1:-1:-1;56862:27:0::2;;::::0;;::::2;::::0;:15;::::2;:27;:::i;:::-;:41;::::0;56893:9:::2;56862:41;:::i;:::-;56823:35;56842:16:::0;56823;:35:::2;:::i;:::-;:80;;56815:94;;;::::0;::::2;::::0;;14894:2:1;56815:94:0::2;::::0;::::2;14876:21:1::0;14933:1;14913:18;;;14906:29;14971:3;14951:18;;;14944:31;14992:18;;56815:94:0::2;14692:324:1::0;56815:94:0::2;56589:332;;56933:49;56941:8;56951;56961:9;56972;56933:7;:49::i;:::-;56998:66;::::0;;15252:25:1;;;15308:2;15293:18;;15286:34;;;15336:18;;;15329:34;;;15394:2;15379:18;;15372:34;;;56998:66:0::2;::::0;::::2;::::0;57003:10:::2;::::0;56998:66:::2;::::0;15239:3:1;15224:19;56998:66:0::2;;;;;;;-1:-1:-1::0;;47687:1:0;47676:8;:12;-1:-1:-1;;;;;;;;;55114:1958:0:o;9899:156::-;9972:4;9989:36;9998:10;10010:7;10019:5;9989:8;:36::i;:::-;-1:-1:-1;10043:4:0;9899:156;;;;:::o;60498:829::-;47606:8;;47618:1;47606:13;47598:22;;;;;;47652:1;47641:8;:12;43978:45:::1;44007:15;43978:28;:45::i;:::-;60587:17:::2;::::0;;;60673:42:::2;:14;60707:7:::0;60673:33:::2;:42::i;:::-;60757:6;::::0;60586:129;;-1:-1:-1;60586:129:0;;-1:-1:-1;60586:129:0;-1:-1:-1;60586:129:0;-1:-1:-1;60757:6:0::2;60745:18:::0;;::::2;60757:6:::0;::::2;60745:18;::::0;60799:42:::2;;60829:12;60799:42;;;60811:15;60799:42;60774:13;:68:::0;;:13:::2;::::0;:68:::2;::::0;;;::::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;60878:9;:42;;60905:15;60878:42;;;60890:12;60878:42;60853:13;:68:::0;;:13:::2;::::0;:68:::2;::::0;;;;;::::2;;;;:::i;:::-;::::0;;::::2;::::0;;::::2;;::::0;;;::::2;::::0;;::::2;::::0;;;::::2;;::::0;;::::2;;::::0;;-1:-1:-1;;60994:32:0;;;:23;:32:::2;::::0;;;;:43:::2;;:50:::0;;;::::2;::::0;::::2;::::0;;61096:52:::2;61110:8:::0;61120:10:::2;61132:15:::0;61096:13:::2;:52::i;:::-;61159:50;61173:9;61184:10;61196:12;61159:13;:50::i;:::-;61227:92;::::0;;15923:25:1;;;61227:92:0::2;16045:15:1::0;;;16040:2;16025:18;;16018:43;16077:18;;;16070:34;;;16140:15;;;16135:2;16120:18;;16113:43;16187:3;16172:19;;16165:35;;;61247:10:0::2;::::0;61227:92:::2;::::0;15910:3:1;15895:19;61227:92:0::2;;;;;;;-1:-1:-1::0;;47687:1:0;47676:8;:12;-1:-1:-1;;;;60498:829:0:o;10219:313::-;10327:15;;;10306:4;10327:15;;;:9;:15;;;;;;;;10343:10;10327:27;;;;;;;;10358:14;10327:45;10323:143;;10419:15;;;;;;;:9;:15;;;;;;;;10435:10;10419:27;;;;;;;;:35;;10449:5;;10419:35;:::i;:::-;10389:15;;;;;;;:9;:15;;;;;;;;10405:10;10389:27;;;;;;;:65;10323:143;10476:26;10486:4;10492:2;10496:5;10476:9;:26::i;:::-;-1:-1:-1;10520:4:0;10219:313;;;;;:::o;46785:47::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;46785:47:0;:::o;69046:517::-;69162:17;69190:19;69245:14;:22;;;69235:7;:32;69227:41;;;;;;69298:45;69393:32;;;:23;:32;;;;;:46;;;69346:94;;69377:14;;69393:46;;69346:30;:94::i;:::-;69298:142;;69481:74;69520:9;69531:7;69540:14;69481:38;:74::i;:::-;69451:104;;;;-1:-1:-1;69046:517:0;-1:-1:-1;;;;69046:517:0:o;64303:310::-;47606:8;;47618:1;47606:13;47598:22;;;;;;47652:1;47641:8;:12;64433:40;;:58;-1:-1:-1;64433:58:0;::::1;::::0;:95:::1;;;64513:15;64495:14;:33;;64433:95;64425:104;;;::::0;::::1;;64561:44;64590:14;64561:28;:44::i;:::-;-1:-1:-1::0;47687:1:0;47676:8;:12;64303:310::o;67040:533::-;67138:33;67182;67233:27;67300:14;:32;;;67282:15;:50;;;;:::i;:::-;67263:70;;:15;:70;:::i;:::-;67372:77;;;;:56;:77;;;;;;;;;67488:56;:77;;;;;;;67372;;67488;;-1:-1:-1;67040:533:0;-1:-1:-1;;;67040:533:0:o;67643:528::-;67738:36;67785;67839:27;67906:14;:32;;;67888:15;:50;;;;:::i;:::-;67869:70;;:15;:70;:::i;:::-;67981;;;;:49;:70;;;;;;;;;68093:49;:70;;;;;;;67981;;68093;;-1:-1:-1;67643:528:0;-1:-1:-1;;;67643:528:0:o;49522:327::-;49627:7;;;;49613:10;:21;49605:30;;;;;;49688:6;:16;;;;;;;;;;;;;;;;49715:6;:16;;;;;;;;;;;;49823:17;;22814:21;:30;;;;;;;;;;22855:21;:30;;;;;;;;;;49806:15;22896:40;:68;49762:14;22975:52;49522:327;;:::o;49762:79::-;49522:327;;:::o;69681:262::-;69764:17;69792:19;69829:37;69850:15;69829:20;:37::i;:::-;69884:51;69910:7;69919:15;69884:25;:51::i;:::-;69877:58;;;;69681:262;;;:::o;68226:536::-;68306:10;68327:27;68365:16;68392:13;68416:21;68448:20;68504:14;:22;;;68494:7;:32;68486:41;;;;;;-1:-1:-1;;;68557:37:0;68597:32;;;-1:-1:-1;;68597:23:0;:32;;-1:-1:-1;68597:32:0;;;68648:8;;68658:25;;;;68685:14;;;;68701:11;;;;68714:19;;;;68735:18;;;;;68648:8;;68658:25;;68685:14;;68701:11;;;;;68714:19;;;;68735:18;;;68226:536::o;46975:211::-;47060:22;:29;47037:4;;47060:118;;-1:-1:-1;47177:1:0;;46975:211::o;47060:118::-;47096:22;47119:29;;:33;;47151:1;;47119:33;:::i;:::-;47096:57;;;;;;;;:::i;:::-;;;;;;;;;;;:78;;;47053:125;;46975:211;:::o;47192:::-;47277:22;:29;47254:4;;47277:118;;-1:-1:-1;47394:1:0;;46975:211::o;47277:118::-;47313:22;47336:29;;:33;;47368:1;;47336:33;:::i;:::-;47313:57;;;;;;;;:::i;:::-;;;;;;;;;;;:78;;;47270:125;;47192:211;:::o;52135:1272::-;52211:14;47606:8;;47618:1;47606:13;47598:22;;;;;;47652:1;47641:8;:12;43978:45:::1;44007:15;43978:28;:45::i;:::-;52239:17:::2;52258::::0;52280:13:::2;48702:8:::0;;;;;;;48712;;;;;;;48722:18;;;;;;;48564:185;52280:13:::2;-1:-1:-1::0;52379:13:0::2;::::0;52344:6:::2;::::0;52335:41:::2;::::0;;;;52370:4:::2;52335:41;::::0;::::2;3383:74:1::0;52238:55:0;;-1:-1:-1;52238:55:0;;-1:-1:-1;52319:13:0::2;::::0;52379::::2;::::0;;::::2;::::0;52344:6:::2;;::::0;52335:26:::2;::::0;3356:18:1;;52335:41:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:57;;;;:::i;:::-;52463:13;::::0;52428:6:::2;::::0;52419:41:::2;::::0;;;;52454:4:::2;52419:41;::::0;::::2;3383:74:1::0;52319:73:0;;-1:-1:-1;52403:13:0::2;::::0;52463;;;::::2;;;::::0;52428:6:::2;::::0;;::::2;::::0;52419:26:::2;::::0;3356:18:1;;52419:41:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:57;;;;:::i;:::-;52403:73:::0;-1:-1:-1;52487:12:0::2;52502:20;;::::0;::::2;:8:::0;:20:::2;:::i;:::-;52487:35:::0;-1:-1:-1;52533:12:0::2;52548:20;;::::0;::::2;:8:::0;:20:::2;:::i;:::-;52533:35;;52581:10;52594:30;52603:9;52614;52594:8;:30::i;:::-;52635:17;52655:11:::0;;52581:43;;-1:-1:-1;52759:17:0;;;52755:341:::2;;46065:7;52805:28;52815:17;52825:7:::0;52815;:17:::2;:::i;:::-;52805:9;:28::i;:::-;:48;;;;:::i;:::-;52793:60;;52868:36;52882:1;46065:7;52868:5;:36::i;:::-;52755:341;;;53004:80;53013:34;::::0;::::2;:22;53023:12:::0;53013:7;:22:::2;:::i;:::-;:34;;;;:::i;:::-;53049;::::0;::::2;:22;53059:12:::0;53049:7;:22:::2;:::i;:::-;:34;;;;:::i;:::-;53004:8;:80::i;:::-;52992:92;;52755:341;53126:1;53114:9;:13;53106:22;;;::::0;::::2;;53172:20;53178:2;53182:9;53172:5;:20::i;:::-;53205:49;53213:8;53223;53233:9;53244;53205:7;:49::i;:::-;53269:5;53265:44;;;53301:8;::::0;53284:25:::2;::::0;53301:8:::2;::::0;;::::2;::::0;::::2;::::0;53289::::2;53284:25;:::i;:::-;53276:5;:33:::0;53265:44:::2;53365:34;::::0;;5900:25:1;;;5956:2;5941:18;;5934:34;;;53370:10:0::2;::::0;53365:34:::2;::::0;5873:18:1;53365:34:0::2;;;;;;;-1:-1:-1::0;;47687:1:0;47676:8;:12;-1:-1:-1;52135:1272:0;;;-1:-1:-1;;;;;;52135:1272:0:o;59867:567::-;60000:15;47606:8;;47618:1;47606:13;47598:22;;;;;;47652:1;47641:8;:12;44512:14:::1;::::0;;;::::1;;;:23;44504:32;;;::::0;::::1;;43978:45:::2;44007:15;43978:28;:45::i;:::-;60028:12:::3;60043:28;60061:9;60043:17;:28::i;:::-;60028:43;;60107:7;60082:13;;:33;;;;;;;;;;;;;;;;:::i;:::-;::::0;;::::3;::::0;;;::::3;;::::0;;::::3;;::::0;;::::3;::::0;;::::3;;;::::0;;;60154:13:::3;::::0;60142:8:::3;::::0;60082:33;;-1:-1:-1;60134:33:0::3;::::0;60154:13;;;;::::3;::::0;::::3;::::0;60142:8;::::3;::::0;::::3;60134:33;:::i;:::-;:54;;60126:63;;;::::0;::::3;;60222:67;:14;60258:7:::0;60267:21;60222:35:::3;:67::i;:::-;60316:10;60300:27;::::0;;;:15:::3;:27:::0;;;;;;;:41;;::::3;::::0;::::3;::::0;;;;;;;;;;;::::3;::::0;;;60357:69;;4717:25:1;;;4758:18;;;4751:34;;;4801:18;;;4794:34;;;60300:41:0;;-1:-1:-1;60316:10:0;60357:69:::3;::::0;4705:2:1;4690:18;60357:69:0::3;;;;;;;;-1:-1:-1::0;47687:1:0;47676:8;:12;59867:567;;-1:-1:-1;;59867:567:0:o;61391:870::-;61491:15;61508:17;61527:19;47606:8;;47618:1;47606:13;47598:22;;;;;;47652:1;47641:8;:12;43978:45:::1;44007:15;43978:28;:45::i;:::-;61560:20:::2;::::0;;61621:56:::2;:14;61669:7:::0;61621:47:::2;:56::i;:::-;61708:6;::::0;61559:118;;-1:-1:-1;61559:118:0;;-1:-1:-1;61559:118:0;-1:-1:-1;61708:6:0::2;::::0;;::::2;61692:22:::0;;::::2;::::0;61688:156:::2;;61731:13;:34:::0;;61756:8;;61731:13;::::2;::::0;:34:::2;::::0;61756:8;;61731:34:::2;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;61688:156;;;61823:8;61798:13;;:34;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;61688:156;61920:12;61916:68;;;61934:32;::::0;;;:23;:32:::2;::::0;;;;:43:::2;;:50:::0;;;::::2;::::0;::::2;::::0;;61916:68:::2;62036:49;62050:12;62064:10;62076:8;62036:13;:49::i;:::-;62103:92;::::0;;17414:25:1;;;17470:2;17455:18;;17448:34;;;17525:14;;17518:22;17498:18;;;17491:50;62103:92:0;;::::2;::::0;::::2;::::0;62137:10:::2;::::0;62103:92:::2;::::0;;;;17402:2:1;62103:92:0;;::::2;47687:1:::0;47676:8;:12;62216;62230;;-1:-1:-1;62230:12:0;-1:-1:-1;61391:870:0;-1:-1:-1;;61391:870:0:o;46724:52::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;47984:572::-;48176:21;;;48147:26;48176:21;;;:15;:21;;;;;;;48147:50;;;;;;;;;;;;;;;;;48086:48;;48147:26;:50;;48176:21;48147:50;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48208:24;48254:6;48235:9;:16;:25;;;;:::i;:::-;48208:52;;48271:20;48294:33;48303:5;48310:16;48294:8;:33::i;:::-;48271:56;;48386:12;48356:43;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;48356:43:0;;;;;;;;;;;;;;;48338:61;;48417:9;48412:137;48436:12;48432:1;:16;48412:137;;;48491:23;:46;48515:9;48525:10;48534:1;48525:6;:10;:::i;:::-;48515:21;;;;;;;;:::i;:::-;;;;;;;;;;;;48491:46;;;;;;;;;;;;;-1:-1:-1;48491:46:0;48470:67;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:18;;;;48486:1;;48470:18;;;;;;:::i;:::-;;;;;;:67;;;;48450:3;;;;;:::i;:::-;;;;48412:137;;;;48136:420;;;47984:572;;;;;:::o;53519:1483::-;53595:12;53609;47606:8;;47618:1;47606:13;47598:22;;;;;;47652:1;47641:8;:12;43978:45:::1;44007:15;43978:28;:45::i;:::-;53635:17:::2;53654::::0;53676:13:::2;48702:8:::0;;;;;;;48712;;;;;;;48722:18;;;;;;;48564:185;53676:13:::2;-1:-1:-1::0;53733:6:0::2;::::0;53783::::2;::::0;53876:13:::2;::::0;53831:42:::2;::::0;;;;53867:4:::2;53831:42;::::0;::::2;3383:74:1::0;53634:55:0;;-1:-1:-1;53634:55:0;;-1:-1:-1;53733:6:0::2;::::0;;::::2;::::0;53783;::::2;::::0;53715:15:::2;::::0;53876:13:::2;::::0;;::::2;::::0;53733:6;;53831:27:::2;::::0;3356:18:1;;53831:42:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:58;;;;:::i;:::-;53961:13;::::0;53916:42:::2;::::0;;;;53952:4:::2;53916:42;::::0;::::2;3383:74:1::0;53815::0;;-1:-1:-1;53900:13:0::2;::::0;53961;;;::::2;;;::::0;53916:27:::2;::::0;::::2;::::0;::::2;::::0;3356:18:1;;53916:42:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:58;;;;:::i;:::-;54020:4;53985:14;54002:24:::0;;;:9:::2;:24;::::0;;;;;53900:74;;-1:-1:-1;54052:30:0::2;54061:9:::0;54072;54052:8:::2;:30::i;:::-;54093:17;54113:11:::0;54039:43;;-1:-1:-1;54113:11:0;54223:20:::2;54235:8:::0;54223:9;:20:::2;:::i;:::-;:35;;;;:::i;:::-;54213:45:::0;-1:-1:-1;54350:12:0;54327:20:::2;54339:8:::0;54327:9;:20:::2;:::i;:::-;:35;;;;:::i;:::-;54317:45;;54439:1;54429:7;:11;:26;;;;;54454:1;54444:7;:11;54429:26;54421:35;;;::::0;::::2;;54500:31;54514:4;54521:9;54500:5;:31::i;:::-;54542:35;54556:7;54565:2;54569:7;54542:13;:35::i;:::-;54588;54602:7;54611:2;54615:7;54588:13;:35::i;:::-;54690:13;::::0;54645:42:::2;::::0;;;;54681:4:::2;54645:42;::::0;::::2;3383:74:1::0;54690:13:0::2;::::0;;::::2;::::0;54645:27:::2;::::0;::::2;::::0;::::2;::::0;3356:18:1;;54645:42:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:58;;;;:::i;:::-;54770:13;::::0;54725:42:::2;::::0;;;;54761:4:::2;54725:42;::::0;::::2;3383:74:1::0;54634:69:0;;-1:-1:-1;54770:13:0;;::::2;;;::::0;54725:27:::2;::::0;::::2;::::0;::::2;::::0;3356:18:1;;54725:42:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:58;;;;:::i;:::-;54714:69;;54796:49;54804:8;54814;54824:9;54835;54796:7;:49::i;:::-;54860:5;54856:44;;;54892:8;::::0;54875:25:::2;::::0;54892:8:::2;::::0;;::::2;::::0;::::2;::::0;54880::::2;54875:25;:::i;:::-;54867:5;:33:::0;54856:44:::2;54956:38;::::0;;5900:25:1;;;5956:2;5941:18;;5934:34;;;54956:38:0::2;::::0;::::2;::::0;54961:10:::2;::::0;54956:38:::2;::::0;5873:18:1;54956:38:0::2;;;;;;;53623:1379;;;;;;;;;47687:1:::0;47676:8;:12;;;;53519:1483;;;:::o;47704:130::-;47805:21;;;;;;;:15;:21;;;;;;;;47798:28;;;;;;;;;;;;;;;;;47769:16;;47798:28;;;47805:21;47798:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;47704:130;;;:::o;70049:162::-;44294:7;;44274:42;;;;;;;;44320:10;;44274:56;44294:7;;44274:40;;:42;;;;;;;;;;;;;;44294:7;44274:42;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:56;;;44266:65;;;;;;70156:14:::1;::::0;;;::::1;;;70155:15;70147:24;;;::::0;::::1;;70182:14;:21:::0;;;::::1;::::0;::::1;::::0;;70049:162::o;10063:148::-;10132:4;10149:32;10159:10;10171:2;10175:5;10149:9;:32::i;57121:395::-;47606:8;;47618:1;47606:13;47598:22;;;;;;47652:1;47641:8;:12;43978:45:::1;44007:15;43978:28;:45::i;:::-;57217:6:::2;::::0;57267::::2;::::0;57383:13:::2;::::0;57372:8:::2;::::0;57217:6:::2;::::0;;::::2;::::0;57267;;::::2;::::0;57299:99:::2;::::0;57217:6;;57322:2;;57372:24:::2;::::0;57383:13:::2;::::0;;::::2;::::0;57372:8:::2;:24;:::i;:::-;57326:42;::::0;;;;57362:4:::2;57326:42;::::0;::::2;3383:74:1::0;57326:71:0::2;::::0;;;::::2;::::0;:27:::2;::::0;::::2;::::0;::::2;::::0;3356:18:1;;57326:42:0::2;;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:71;;;;:::i;:::-;57299:13;:99::i;:::-;57493:13;::::0;57482:8:::2;::::0;57409:99:::2;::::0;57423:7;;57432:2;;57482:24:::2;::::0;57493:13:::2;::::0;;;;::::2;::::0;::::2;::::0;57482:8;;::::2;;:24;:::i;:::-;57436:42;::::0;;;;57472:4:::2;57436:42;::::0;::::2;3383:74:1::0;57436:71:0::2;::::0;;;::::2;::::0;:27:::2;::::0;::::2;::::0;::::2;::::0;3356:18:1;;57436:42:0::2;3237:226:1::0;57409:99:0::2;-1:-1:-1::0;;47687:1:0;47676:8;:12;-1:-1:-1;57121:395:0:o;65137:1068::-;65408:40;;65487:13;;65476:8;;65222:17;;;;65408:40;;65222:17;;;;;;65476:24;;65487:13;;;;;65476:8;:24;:::i;:::-;65567:13;;65556:8;;65461:39;;-1:-1:-1;65541:12:0;;65556:24;;65567:13;;;;;;;;;65556:8;;;;;:24;:::i;:::-;65541:39;;65623:58;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;65623:58:0;65713:8;;;;;;65692:29;;65753:8;;;;;;;65732:18;;;:29;65798:13;;;;;65772:23;;;:39;65848:13;;;;;65822:23;;;:39;65874:77;:14;65928;65692:6;65874:53;:77::i;:::-;65991:23;;;;65984:30;;;;;;:::i;:::-;65964:51;;66053:6;:23;;;66046:4;:30;;;;;;:::i;:::-;66026:51;;66113:6;:23;;;66088:49;;66173:6;:23;;;66148:49;;65367:838;;;65137:1068;;;;;;;:::o;59075:567::-;59208:15;47606:8;;47618:1;47606:13;47598:22;;;;;;47652:1;47641:8;:12;44512:14:::1;::::0;;;::::1;;;:23;44504:32;;;::::0;::::1;;43978:45:::2;44007:15;43978:28;:45::i;:::-;59236:12:::3;59251:28;59269:9;59251:17;:28::i;:::-;59290:13;:33:::0;;59236:43;;-1:-1:-1;59236:43:0;;59290:13:::3;::::0;:33:::3;::::0;59236:43;;59290:33:::3;;;:::i;:::-;::::0;;::::3;::::0;;;::::3;;::::0;;::::3;;::::0;;::::3;::::0;;::::3;;;::::0;;;59362:13:::3;::::0;59350:8:::3;::::0;59290:33;;-1:-1:-1;59342:33:0::3;::::0;59362:13;;::::3;::::0;59350:8;::::3;59342:33;:::i;:::-;:54;;59334:63;;;::::0;::::3;;59430:67;:14;59466:7:::0;59475:21;59430:35:::3;:67::i;:::-;59524:10;59508:27;::::0;;;:15:::3;:27:::0;;;;;;;:41;;::::3;::::0;::::3;::::0;;;;;;;;;;;::::3;::::0;;;59565:69;;4717:25:1;;;4758:18;;;4751:34;;;4801:18;;;4794:34;;;59508:41:0;;-1:-1:-1;59524:10:0;59565:69:::3;::::0;4705:2:1;4690:18;59565:69:0::3;4515:319:1::0;10540:661:0;10695:15;10683:8;:27;;10675:36;;;;;;10838:16;;10934:13;;;10733:14;10934:13;;;:6;:13;;;;;:15;;10733:14;;10838:16;8538:66;;10911:5;;10918:7;;10927:5;;10934:15;10733:14;10934:15;;;:::i;:::-;;;;-1:-1:-1;10883:77:0;;;;;;18484:25:1;;;;18528:42;18606:15;;;18586:18;;;18579:43;18658:15;;;;18638:18;;;18631:43;18690:18;;;18683:34;18733:19;;;18726:35;18777:19;;;18770:35;;;18456:19;;10883:77:0;;;;;;;;;;;;10873:88;;;;;;10774:202;;;;;;;;19086:66:1;19074:79;;19178:1;19169:11;;19162:27;;;;19214:2;19205:12;;19198:28;19251:2;19242:12;;18816:444;10774:202:0;;;;;;;;;;;;;;10750:237;;10774:202;10750:237;;;;10998:24;11025:26;;;;;;;;;19492:25:1;;;19565:4;19553:17;;19533:18;;;19526:45;;;;19587:18;;;19580:34;;;19630:18;;;19623:34;;;10750:237:0;;-1:-1:-1;10998:24:0;11025:26;;19464:19:1;;11025:26:0;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;11025:26:0;;;;;;-1:-1:-1;;11070:30:0;;;;;;;:59;;;11124:5;11104:25;;:16;:25;;;11070:59;11062:68;;;;;;11162:31;11171:5;11178:7;11187:5;11162:8;:31::i;:::-;10664:537;;10540:661;;;;;;;:::o;57565:271::-;47606:8;;47618:1;47606:13;47598:22;;;;;;47652:1;47641:8;:12;43978:45:::1;44007:15;43978:28;:45::i;:::-;57699:13:::2;::::0;57664:6:::2;::::0;57655:41:::2;::::0;;;;57690:4:::2;57655:41;::::0;::::2;3383:74:1::0;57633:195:0::2;::::0;57699:13:::2;;::::0;57664:6:::2;;::::0;57655:26:::2;::::0;3356:18:1;;57655:41:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:57;;;;:::i;:::-;57771:13;::::0;57736:6:::2;::::0;57727:41:::2;::::0;;;;57762:4:::2;57727:41;::::0;::::2;3383:74:1::0;57771:13:0;;;::::2;;;::::0;57736:6:::2;::::0;;::::2;::::0;57727:26:::2;::::0;3356:18:1;;57727:41:0::2;;;;;;;;;;;;;;;;;::::0;::::2;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:57;;;;:::i;:::-;57799:8;::::0;::::2;::::0;;::::2;::::0;57809;;::::2;;57633:7;:195::i;:::-;47687:1:::0;47676:8;:12;57565:271::o;62427:1727::-;62514:14;;;;;;;62511:26;;;62427:1727;:::o;62511:26::-;65081:40;;65062:15;:59;62572:27;;62427:1727;:::o;62572:27::-;62623:58;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;62623:58:0;62713:8;;;;;;62692:29;;62753:8;;;;;;;62732:18;;;:29;62798:13;;;;;62772:23;;;:39;62848:13;;;;;62822:23;;;:39;62874:73;:14;62924;62692:6;62874:49;:73::i;:::-;62984:23;;;;62960:13;:48;;63043:23;;;;62960:48;63019;;;;;;;;;62960;;63019;;;;;;;;;;63118:18;;63178;;;;62960:13;63242:24;63259:7;63242:14;:24;:::i;:::-;63363:18;;63210:57;;-1:-1:-1;63363:18:0;;;;;;;63345:36;;;63472:15;;;;;;:71;;-1:-1:-1;63507:8:0;;;63492:23;;;63507:8;;63492:23;;;:50;;-1:-1:-1;63534:8:0;;;63519:23;;;63534:8;;;;;63519:23;;63492:50;63467:680;;;63565:410;63605:15;63639:6;:18;;;63676:6;:18;;;63713:6;:23;;;63755:6;:23;;;63797:6;:19;;;63835:6;:19;;;63873:6;:17;;;63909:6;:17;;;63945:6;:15;;;63565:410;;;;;;;;;;;;;;20096:10:1;20084:23;;;;20066:42;;20127:30;20193:15;;;20188:2;20173:18;;20166:43;20245:15;;;;20240:2;20225:18;;20218:43;20292:2;20277:18;;20270:34;;;;20335:3;20320:19;;20313:35;;;;20379:3;20364:19;;20357:35;20423:3;20408:19;;20401:35;20467:3;20452:19;;20445:35;20511:3;20496:19;;20489:35;;;;20555:3;20540:19;;20533:35;20053:3;20038:19;;19668:906;63565:410:0;;;;;;;;64024:8;;63990:53;;;;;;;;;;;64024:8;;;;64034;;;;63990:7;:53::i;:::-;63467:680;;;64076:8;:22;;;64113;;;;;;;;;64076;;;64113;;;;63467:680;62498:1656;;;;;62427:1727;:::o;49033:284::-;46131:34;;;;;;;;;;;;;;;;;49161:43;;49150:10;20771:55:1;;;49161:43:0;;;20753:74:1;20843:18;;;;20836:34;;;49161:43:0;;;;;;;;;;20726:18:1;;;;49161:43:0;;;;;;;;;;;;;49150:55;;-1:-1:-1;;;;49150:10:0;;;:55;;49161:43;49150:55;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;49114:91;;;;49224:7;:57;;;;-1:-1:-1;49236:11:0;;:16;;:44;;;49267:4;49256:24;;;;;;;;;;;;:::i;:::-;49216:74;;;;;;;;;;;21644:2:1;21626:21;;;21683:1;21663:18;;;21656:29;21721:6;21716:2;21701:18;;21694:34;21760:2;21745:18;;21442:327;49216:74:0;49103:214;;49033:284;;;:::o;49934:1171::-;50057:13;;50074:17;;50046:24;;50057:13;;50046:8;:24;:::i;:::-;:45;;:94;;;;-1:-1:-1;50106:13:0;;50123:17;;50095:24;;50106:13;;;;;50095:8;:24;:::i;:::-;:45;;50046:94;50038:111;;;;;;;;;;;21976:2:1;21958:21;;;22015:1;21995:18;;;21988:29;22053:6;22048:2;22033:18;;22026:34;22092:2;22077:18;;21774:327;50038:111:0;50172:21;50203:25;50221:7;50203:15;:25;:::i;:::-;50326:18;;50172:57;;-1:-1:-1;50326:18:0;;;;;;;50309:35;;;50386:15;;;;;;:33;;-1:-1:-1;50405:14:0;;;;;50386:33;:51;;;;-1:-1:-1;50423:14:0;;;;;50386:51;50382:537;;;50523:22;50573:311;;;;;;;;50615:14;50573:311;;;;;;50734:11;50681:64;;50686:44;50720:9;50686:27;50703:9;50686:16;:27::i;:::-;:33;;;;:44::i;:::-;50681:50;;:64;50656:22;:20;:22::i;:::-;:89;50573:311;;;;50850:11;50797:64;;50802:44;50836:9;50802:27;50819:9;50802:16;:27::i;:44::-;50797:50;;:64;50772:22;:20;:22::i;:::-;:89;50573:311;;50523:380;;;;;;;;-1:-1:-1;50523:380:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;50382:537;50942:8;:28;;51022:35;;;;;;50942:28;50981;;;;;;;;;;;50942;;;50981;;;;;51022:35;;;;;;;;;51073:24;;;51078:8;;;;;;;;;;22329:34:1;;51088:8:0;;;;;;;22394:2:1;22379:18;;22372:43;51073:24:0;;22253:18:1;51073:24:0;;;;;;;50027:1078;;49934:1171;;;;:::o;9500:169::-;9581:16;;;;;;;;:9;:16;;;;;;;;:25;;;;;;;;;;;;;:33;;;9630:31;;3833:25:1;;;9630:31:0;;3806:18:1;9630:31:0;;;;;;;;9500:169;;;:::o;25559:756::-;25661:17;25863:32;;;:23;;;:32;;;;;25917:18;;;;25958:19;;;;25917:18;25958:19;;;;25661:17;25917:18;;;25661:17;;;26020:39;25863:14;25958:19;26020:12;:39::i;:::-;25990:69;;26104:82;26125:9;26136:7;26145:14;:40;;;26104:20;:82::i;:::-;26207:11;;;;26070:116;;-1:-1:-1;26070:116:0;-1:-1:-1;26207:25:0;:11;26222:10;26207:25;:70;;;;;26252:1;26237:12;:16;:39;;;;26275:1;26257:15;:19;26237:39;26199:79;;;;;;25745:570;;25559:756;;;;;;;:::o;9677:214::-;9771:15;;;;;;;:9;:15;;;;;;:23;;9789:5;;9771:23;:::i;:::-;9753:15;;;;;;;;:9;:15;;;;;;:41;;;;9821:13;;;;;;;:21;;9837:5;;9821:21;:::i;:::-;9805:13;;;;;;;;:9;:13;;;;;;;:37;;;;9858:25;;;;;;;;;;9877:5;3833:25:1;;3821:2;3806:18;;3687:177;23092:245:0;23252:21;;;;23191:27;;23252:21;23243:30;;;23252:21;;23243:30;:86;;23304:14;:25;;23243:86;;;23276:14;:25;;23243:86;23231:98;23092:245;-1:-1:-1;;;23092:245:0:o;40553:1175::-;40676:17;40750:28;;;:19;;;:28;;;;;;40676:17;;40797:16;40789:25;;;;;;40825:19;40847:30;;;:21;;;:30;;;;;;;;;40923:34;;;:43;;;;;;;41065:28;;;41061:660;;;41110:28;41141:46;;;:33;;;:46;;;;;;35770:6;20961:7;41280:47;;;41279:64;;:97;41278:106;41264:120;;41429:4;41414:19;;41095:350;41061:660;;;35770:6;20961:7;41552:99;;41606:12;41578:24;41553:9;:22;;;:49;41552:66;:99;;;;;:::i;:::-;;41551:108;;;;;:::i;:::-;;41537:122;;41704:5;41689:20;;41061:660;40716:1012;;;40553:1175;;;;;;:::o;51195:828::-;51268:10;51291:13;51327:7;;;;;;;;;;;51307:34;;;:36;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;51406:5;;51362:19;;;;;;;-1:-1:-1;51291:52:0;;-1:-1:-1;51406:5:0;51437:579;;51467:11;;51463:483;;51499:10;51512:38;51522:27;;;;;;:15;;:27;:::i;51512:38::-;51499:51;;51569:14;51586:17;51596:6;51586:9;:17::i;:::-;51569:34;;51634:9;51626:5;:17;51622:309;;;51668:14;51700:17;51708:9;51700:5;:17;:::i;:::-;51685:11;;:33;;;;:::i;:::-;51668:50;-1:-1:-1;51741:16:0;51774:9;51761;:5;51769:1;51761:9;:::i;:::-;51760:23;;;;:::i;:::-;51741:42;-1:-1:-1;51806:14:0;51823:23;51741:42;51823:9;:23;:::i;:::-;51806:40;-1:-1:-1;51873:13:0;;51869:42;;51888:23;51894:5;51901:9;51888:5;:23::i;:::-;51645:286;;;51622:309;51480:466;;51463:483;51437:579;;;51967:11;;51963:53;;52003:1;51995:5;:9;51963:53;51280:743;;51195:828;;;;:::o;11555:303::-;11600:6;11627:1;11623;:5;11619:232;;;-1:-1:-1;11649:1:0;11665:6;11674:5;11678:1;11649;11674:5;:::i;:::-;:9;;11682:1;11674:9;:::i;:::-;11665:18;;11698:92;11709:1;11705;:5;11698:92;;;11735:1;-1:-1:-1;11735:1:0;11773;11735;11760:5;11735:1;11760;:5;:::i;:::-;:9;;;;:::i;:::-;11759:15;;;;:::i;:::-;11755:19;;11698:92;;;11630:171;11555:303;;;:::o;11619:232::-;11811:6;;11807:44;;-1:-1:-1;11838:1:0;11807:44;11555:303;;;:::o;9086:195::-;9173:5;9159:11;;:19;;;;:::i;:::-;9145:11;:33;;;9205:13;;;;;:9;:13;;;;;;:21;;9221:5;;9205:21;:::i;:::-;9189:13;;;;;;;:9;:13;;;;;;:37;;;;9242:31;;9189:13;;;9242:31;;;;9267:5;3833:25:1;;3821:2;3806:18;;3687:177;9242:31:0;;;;;;;;9086:195;;:::o;11341:96::-;11393:6;11420:1;11416;:5;:13;;11428:1;11416:13;;;-1:-1:-1;11424:1:0;;11412:17;-1:-1:-1;11341:96:0:o;58464:386::-;58589:6;;58580:41;;;;;58615:4;58580:41;;;3383:74:1;58524:7:0;;;;58589:6;;;;;58580:26;;3356:18:1;;58580:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;58704:6;;58568:53;;-1:-1:-1;58672:77:0;;58704:6;;58712:10;58732:4;58739:9;58672:31;:77::i;:::-;58803:6;;58794:41;;;;;58829:4;58794:41;;;3383:74:1;58838:4:0;;58803:6;;;58794:26;;3356:18:1;;58794:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:48;;;;:::i;23910:283::-;24108:21;;;;24131;;;;24045:7;;24072:113;;24092:14;;24108:21;;;;;24131;24154:7;24163:21;24072:19;:113::i;:::-;24065:120;23910:283;-1:-1:-1;;;;23910:283:0:o;26407:684::-;26523:20;26700:32;;;:23;;;:32;;;;;26758:18;;;;26848:19;;;;26758:18;;;;;26523:20;;;26700:32;;26523:20;;26819:49;;26700:14;;26848:19;26819:12;:49::i;:::-;26789:79;;26906:87;26932:9;26943:7;26952:14;:40;;;26906:25;:87::i;:::-;27014:11;;;;26879:114;;-1:-1:-1;26879:114:0;-1:-1:-1;27014:25:0;:11;27029:10;27014:25;:41;;;;;27054:1;27043:8;:12;27014:41;27006:50;;;;;;26582:509;;26407:684;;;;;:::o;9289:203::-;9368:15;;;;;;;:9;:15;;;;;;:23;;9386:5;;9368:23;:::i;:::-;9350:15;;;;;;;:9;:15;;;;;:41;;;;9416:11;:19;;9430:5;;9416:19;:::i;:::-;9402:11;:33;;;9451;;3833:25:1;;;9451:33:0;;;;;;3821:2:1;3806:18;9451:33:0;3687:177:1;32378:2794:0;32606:40;;;;32697:32;;32565:38;32697:32;32821:50;32697:32;32606:40;32821:50;:::i;:::-;32787:85;;:30;:85;:::i;:::-;:105;;;;:::i;:::-;33028:25;;;33244:27;;33095:25;;;33310:27;;32752:140;;-1:-1:-1;33028:25:0;;33350:1188;33384:14;33357:24;:41;33350:1188;;;33553:1;33483:67;;;:41;;;:67;;;;;;:71;;;:163;;-1:-1:-1;33645:1:0;33575:67;;;:41;;;:67;;;;;;:71;;33483:163;33479:988;;;33720:29;33752:57;33779:30;33752:24;:57;:::i;:::-;33720:89;-1:-1:-1;33828:24:0;20961:7;33855:41;33720:89;33855:17;:41;:::i;:::-;:74;;;;:::i;:::-;33828:101;-1:-1:-1;33948:24:0;20961:7;33975:41;33995:21;33975:17;:41;:::i;:::-;:74;;;;:::i;:::-;33948:101;;34070:87;34107:13;34122:16;34140;34070:36;:87::i;:::-;-1:-1:-1;;34199:67:0;;;;:41;;;:67;;;;;;34178:88;;;;:::i;:::-;34306:67;;;;:41;;;:67;;;;;;34178:88;;-1:-1:-1;34285:88:0;;;;:::i;:::-;;;34427:24;34394:57;;33648:819;;;33479:988;34481:45;34509:17;34481:45;;:::i;:::-;;;33350:1188;;;34656:14;34622:30;:48;34618:547;;34736:29;34768:47;34785:30;34768:14;:47;:::i;:::-;34736:79;-1:-1:-1;34830:24:0;20961:7;34857:41;34736:79;34857:17;:41;:::i;:::-;:74;;;;:::i;:::-;34830:101;-1:-1:-1;34946:24:0;20961:7;34973:41;34993:21;34973:17;:41;:::i;:::-;:74;;;;:::i;:::-;34946:101;;35064:87;35101:13;35116:16;35134;35064:36;:87::i;:::-;;;34672:493;;;34618:547;32552:2620;;;;;;;32378:2794;;;:::o;57965:386::-;58090:6;;58081:41;;;;;58116:4;58081:41;;;3383:74:1;58025:7:0;;;;58090:6;;;;;58081:26;;3356:18:1;;58081:41:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;58205:6;;58069:53;;-1:-1:-1;58173:77:0;;58205:6;;58213:10;58233:4;58240:9;58173:31;:77::i;:::-;58304:6;;58295:41;;;;;58330:4;58295:41;;;3383:74:1;58339:4:0;;58304:6;;;58295:26;;3356:18:1;;58295:41:0;3237:226:1;23482:283:0;23680:21;;;;23703;;;;23617:7;;23644:113;;23664:14;;23680:21;;;;;23703;23726:7;23735:21;23644:19;:113::i;28880:3402::-;29099:40;;;;29190:32;;29058:38;29190:32;29314:50;29190:32;29099:40;29314:50;:::i;:::-;29280:85;;:30;:85;:::i;:::-;:105;;;;:::i;:::-;29245:140;-1:-1:-1;29521:25:0;;;29588;;;29626:1600;29660:14;29633:24;:41;29626:1600;;;29829:1;29759:67;;;:41;;;:67;;;;;;:71;;;:163;;-1:-1:-1;29921:1:0;29851:67;;;:41;;;:67;;;;;;:71;;29759:163;29755:1400;;;29996:29;30028:57;30055:30;30028:24;:57;:::i;:::-;30131:27;;29996:89;;-1:-1:-1;30104:24:0;;20961:7;;30131:51;;29996:89;;30131:51;:::i;:::-;:84;;;;:::i;:::-;30261:27;;30104:111;;-1:-1:-1;30234:24:0;;20961:7;;30261:51;;30291:21;;30261:51;:::i;:::-;:84;;;;:::i;:::-;30234:111;;30367:17;30386;30407:87;30444:13;30459:16;30477;30407:36;:87::i;:::-;30366:128;;;;30635:49;30662:10;30674:9;30635:26;:49::i;:::-;30703;30730:10;30742:9;30703:26;:49::i;:::-;30888:77;30928:10;30940:24;30888:39;:77::i;:::-;30984;31024:10;31036:24;30984:39;:77::i;:::-;31115:24;31082:57;;29924:1231;;;;;29755:1400;31169:45;31197:17;31169:45;;:::i;:::-;;;29626:1600;;;31344:14;31310:30;:48;31306:899;;31424:29;31456:47;31473:30;31456:14;:47;:::i;:::-;31545:27;;31424:79;;-1:-1:-1;31518:24:0;;20961:7;;31545:51;;31424:79;;31545:51;:::i;:::-;:84;;;;:::i;:::-;31671:27;;31518:111;;-1:-1:-1;31644:24:0;;20961:7;;31671:51;;31701:21;;31671:51;:::i;:::-;:84;;;;:::i;:::-;31644:111;;31773:17;31792;31813:87;31850:13;31865:16;31883;31813:36;:87::i;:::-;31772:128;;;;31961:49;31988:10;32000:9;31961:26;:49::i;:::-;32025;32052:10;32064:9;32025:26;:49::i;:::-;31360:845;;;;;31306:899;-1:-1:-1;;;;;32217:40:0;;;;;:57;-1:-1:-1;28880:3402:0:o;12194:120::-;12244:9;12270:17;12139:6;12270:10;;;:17;:::i;:::-;12266:21;12194:120;-1:-1:-1;;12194:120:0:o;12385:108::-;12445:9;12471:14;12475:10;;;12471:1;:14;:::i;38517:1024::-;38635:20;38710:30;;;:21;;;:30;;;;;;38635:20;;38759:23;;;38751:32;;;;;;38867:17;38887:28;;;:19;;;:28;;;;;;20961:7;38887:28;38942:23;38951:14;38942:6;:23;:::i;:::-;38941:37;;;;:::i;:::-;:70;;;;:::i;:::-;39189:43;;;;:34;;;:43;;;;;;39164:22;;;;38926:85;;-1:-1:-1;35770:6:0;;20961:7;39164:68;;;39163:82;;:115;39162:124;39144:142;;39364:9;39334;:26;;;:39;;;;;;;:::i;:::-;;;;-1:-1:-1;;39415:1:0;39384:28;;;:19;;;:28;;;;;;;;:32;;;39427:21;;;:30;;;;;:34;;;39472:48;;;:40;;;:48;;;;;:61;;39524:9;;39415:1;39472:61;;39524:9;;39472:61;:::i;:::-;;;;;;;;38682:859;;38517:1024;;;;;;:::o;15437:498::-;15708:51;;;15697:10;23268:15:1;;;15708:51:0;;;23250:34:1;23320:15;;;23300:18;;;23293:43;23352:18;;;;23345:34;;;15708:51:0;;;;;;;;;;23162:18:1;;;;15708:51:0;;;;;;;;;;;;;15697:63;;-1:-1:-1;;;;15697:10:0;;;;:63;;15708:51;15697:63;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15661:99;;;;15793:7;:57;;;;-1:-1:-1;15805:11:0;;:16;;:44;;;15836:4;15825:24;;;;;;;;;;;;:::i;:::-;15771:156;;;;;;;23592:2:1;15771:156:0;;;23574:21:1;23631:2;23611:18;;;23604:30;23670:34;23650:18;;;23643:62;23741:19;23721:18;;;23714:47;23778:19;;15771:156:0;23390:413:1;24251:1210:0;24712:32;;24409:7;;24627:15;;24409:7;;24698:46;;24627:15;24698:46;:::i;:::-;24683:62;;:11;:62;:::i;:::-;24653:92;-1:-1:-1;24756:19:0;24653:92;24814:25;:21;24838:1;24814:25;:::i;:::-;24778:32;;:62;;;;:::i;:::-;:84;;;;:::i;:::-;24756:106;-1:-1:-1;24873:19:0;24938:25;24952:11;24756:106;24938:25;:::i;:::-;24895:39;24928:6;20961:7;24895:39;:::i;:::-;:69;;;;:::i;:::-;24873:91;;24999:1;24985:11;:15;24977:24;;;;;;25079:27;25109:34;25122:14;25138:4;25109:12;:34::i;:::-;25079:64;;25154:82;25176:9;25187:14;:22;;;25211:11;25224;25154:21;:82::i;:::-;25327:84;;;;;;;;25333:14;:22;;;25327:84;;;;25357:11;25327:84;;;;25370:11;25327:84;;;;25383:10;25327:84;;;;;;25395:4;25327:84;;;;;;25401:2;25327:84;;;;;;25405:5;25327:84;;;;;25277:14;:23;;:47;25301:14;:22;;;25277:47;;;;;;;;;;;:134;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;25429:14;:22;;;:24;;;;;;;;;:::i;:::-;;;;-1:-1:-1;25422:31:0;24251:1210;-1:-1:-1;;;;;;;;;;;24251:1210:0:o;39901:561::-;40024:19;40045:17;40105:56;40126:9;40137:7;40146:14;40105:20;:56::i;:::-;40075:86;-1:-1:-1;40075:86:0;-1:-1:-1;40174:281:0;;;;40266:1;40235:28;;;:19;;;:28;;;;;:32;40174:281;;;40421:22;;;;40375:43;;;;:34;;;:43;;;;;:68;40174:281;39901:561;;;;;;:::o;27336:1459::-;27539:17;27558;27621:12;27664:13;:30;;;27636:13;:25;;;:58;;;;;;:::i;:::-;27621:73;;27705:12;27748:13;:30;;;27720:13;:25;;;:58;;;;;;:::i;:::-;27705:73;;27855:196;27913:13;:25;;;27855:196;;27953:13;:25;;;27855:196;;27993:16;28024;27855:43;:196::i;:::-;28133:30;;;;27830:221;;-1:-1:-1;27830:221:0;-1:-1:-1;28178:16:0;;28133:42;;27830:221;;28133:42;:::i;:::-;:61;;;;:::i;:::-;28100:30;;;:94;28238:30;;;;28283:16;;28238:42;;28271:9;;28238:42;:::i;:::-;:61;;;;:::i;:::-;28205:30;;;:94;28353:30;;;;28346:37;;:4;:37;:::i;:::-;28310:74;;;;28473:30;;;;28466:37;;:4;:37;:::i;:::-;28430:74;;:25;;;:74;28550:26;;;:39;;28580:9;;28550:26;:39;;28580:9;;28550:39;:::i;:::-;;;-1:-1:-1;28600:26:0;;;:39;;28630:9;;28600:26;:39;;28630:9;;28600:39;:::i;:::-;;;-1:-1:-1;28650:24:0;;;:44;;28678:16;;28650:24;:44;;28678:16;;28650:44;:::i;:::-;;;-1:-1:-1;28705:24:0;;;:44;;28733:16;;28705:24;:44;;28733:16;;28705:44;:::i;:::-;;;-1:-1:-1;28760:22:0;;;:27;;28786:1;;28760:22;:27;;28786:1;;28760:27;:::i;:::-;;;-1:-1:-1;27336:1459:0;;;;-1:-1:-1;27336:1459:0;;-1:-1:-1;;;;27336:1459:0:o;37154:346::-;37259:26;;:31;37255:238;;37440:26;;37391:46;;;37440:26;37391:75;;;;:::i;:::-;37365:22;;;;;:101;;37391:75;;;;37365:101;;;;-1:-1:-1;37154:346:0:o;38148:301::-;38300:56;;;;:40;;;:56;;;;;;38270:86;;38300:56;;:9;;38270:86;;38300:56;;38270:86;:::i;:::-;;;;-1:-1:-1;;38419:22:0;;;;38367:49;;;;:33;;;;:49;;;;;:74;38148:301::o;37562:478::-;37737:17;37707:9;:26;;;:47;;;;;;;:::i;:::-;;;;-1:-1:-1;;37811:22:0;;;;37765:43;;;;:34;;;:43;;;;;;;;:68;;;;37844:21;;;:30;;;;;:44;;;37899:19;;;:28;;;;;:48;;;37958:53;;;:40;;;:53;;;;;:74;;37930:17;;37765:43;37958:74;;37930:17;;37958:74;:::i;:::-;;;;-1:-1:-1;;;;;;37562:478:0:o;17795:1388::-;17970:17;;18170:1;18158:13;;;;;:30;;;18187:1;18175:8;:13;;18158:30;18154:1022;;18345:1;18333:8;:13;18329:847;;18403:20;18426:14;:8;18437:3;18426:14;:::i;:::-;18403:37;-1:-1:-1;18403:37:0;18501:18;:11;18515:4;18501:18;:::i;:::-;18500:38;;;;:::i;:::-;18467:29;18481:15;18467:11;:29;:::i;:::-;:72;;;;:::i;:::-;18455:84;;18348:203;18329:847;;;18582:1;18570:8;:13;18566:610;;18639:20;18662:14;:8;18673:3;18662:14;:::i;:::-;18639:37;-1:-1:-1;18639:37:0;18737:18;:11;18751:4;18737:18;:::i;:::-;18736:38;;;;:::i;:::-;18703:29;18717:15;18703:11;:29;:::i;:::-;:72;;;;:::i;:::-;18691:84;;18585:202;18566:610;;;18875:17;18927:4;18910:14;:8;18921:3;18910:14;:::i;:::-;:21;;;;:::i;:::-;18895:37;;:11;:37;:::i;:::-;18875:57;-1:-1:-1;18947:17:0;18999:4;18982:14;:8;18993:3;18982:14;:::i;:::-;:21;;;;:::i;:::-;18967:37;;:11;:37;:::i;:::-;18947:57;-1:-1:-1;18947:57:0;19044:25;19059:9;19044:11;:25;:::i;:::-;:39;;;;:::i;:::-;19031:53;;:9;:53;:::i;:::-;19019:65;-1:-1:-1;19153:9:0;19124:25;19139:9;19124:11;:25;:::i;:::-;:39;;;;:::i;:::-;19111:53;;:9;:53;:::i;:::-;19099:65;;18860:316;;18566:610;17795:1388;;;;;;;:::o;14:154:1:-;100:42;93:5;89:54;82:5;79:65;69:93;;158:1;155;148:12;69:93;14:154;:::o;173:863::-;270:6;278;286;294;302;355:3;343:9;334:7;330:23;326:33;323:53;;;372:1;369;362:12;323:53;408:9;395:23;385:33;;465:2;454:9;450:18;437:32;427:42;;519:2;508:9;504:18;491:32;532:31;557:5;532:31;:::i;:::-;582:5;-1:-1:-1;638:2:1;623:18;;610:32;661:18;691:14;;;688:34;;;718:1;715;708:12;688:34;756:6;745:9;741:22;731:32;;801:7;794:4;790:2;786:13;782:27;772:55;;823:1;820;813:12;772:55;863:2;850:16;889:2;881:6;878:14;875:34;;;905:1;902;895:12;875:34;950:7;945:2;936:6;932:2;928:15;924:24;921:37;918:57;;;971:1;968;961:12;918:57;173:863;;;;-1:-1:-1;173:863:1;;-1:-1:-1;1002:2:1;994:11;;1024:6;173:863;-1:-1:-1;;;173:863:1:o;1041:258::-;1113:1;1123:113;1137:6;1134:1;1131:13;1123:113;;;1213:11;;;1207:18;1194:11;;;1187:39;1159:2;1152:10;1123:113;;;1254:6;1251:1;1248:13;1245:48;;;1289:1;1280:6;1275:3;1271:16;1264:27;1245:48;;1041:258;;;:::o;1304:442::-;1453:2;1442:9;1435:21;1416:4;1485:6;1479:13;1528:6;1523:2;1512:9;1508:18;1501:34;1544:66;1603:6;1598:2;1587:9;1583:18;1578:2;1570:6;1566:15;1544:66;:::i;:::-;1662:2;1650:15;1667:66;1646:88;1631:104;;;;1737:2;1627:113;;1304:442;-1:-1:-1;;1304:442:1:o;2725:315::-;2793:6;2801;2854:2;2842:9;2833:7;2829:23;2825:32;2822:52;;;2870:1;2867;2860:12;2822:52;2909:9;2896:23;2928:31;2953:5;2928:31;:::i;:::-;2978:5;3030:2;3015:18;;;;3002:32;;-1:-1:-1;;;2725:315:1:o;3869:180::-;3928:6;3981:2;3969:9;3960:7;3956:23;3952:32;3949:52;;;3997:1;3994;3987:12;3949:52;-1:-1:-1;4020:23:1;;3869:180;-1:-1:-1;3869:180:1:o;4054:456::-;4131:6;4139;4147;4200:2;4188:9;4179:7;4175:23;4171:32;4168:52;;;4216:1;4213;4206:12;4168:52;4255:9;4242:23;4274:31;4299:5;4274:31;:::i;:::-;4324:5;-1:-1:-1;4381:2:1;4366:18;;4353:32;4394:33;4353:32;4394:33;:::i;:::-;4054:456;;4446:7;;-1:-1:-1;;;4500:2:1;4485:18;;;;4472:32;;4054:456::o;4839:248::-;4907:6;4915;4968:2;4956:9;4947:7;4943:23;4939:32;4936:52;;;4984:1;4981;4974:12;4936:52;-1:-1:-1;;5007:23:1;;;5077:2;5062:18;;;5049:32;;-1:-1:-1;4839:248:1:o;5979:388::-;6047:6;6055;6108:2;6096:9;6087:7;6083:23;6079:32;6076:52;;;6124:1;6121;6114:12;6076:52;6163:9;6150:23;6182:31;6207:5;6182:31;:::i;:::-;6232:5;-1:-1:-1;6289:2:1;6274:18;;6261:32;6302:33;6261:32;6302:33;:::i;:::-;6354:7;6344:17;;;5979:388;;;;;:::o;7000:247::-;7059:6;7112:2;7100:9;7091:7;7087:23;7083:32;7080:52;;;7128:1;7125;7118:12;7080:52;7167:9;7154:23;7186:31;7211:5;7186:31;:::i;7635:383::-;7712:6;7720;7728;7781:2;7769:9;7760:7;7756:23;7752:32;7749:52;;;7797:1;7794;7787:12;7749:52;7836:9;7823:23;7855:31;7880:5;7855:31;:::i;:::-;7905:5;7957:2;7942:18;;7929:32;;-1:-1:-1;8008:2:1;7993:18;;;7980:32;;7635:383;-1:-1:-1;;;7635:383:1:o;8023:1312::-;8240:2;8292:21;;;8362:13;;8265:18;;;8384:22;;;8211:4;;8240:2;8425;;8443:18;;;;8484:15;;;8211:4;8527:782;8541:6;8538:1;8535:13;8527:782;;;8600:13;;8638:9;;8626:22;;8688:11;;;8682:18;8668:12;;;8661:40;8741:11;;;8735:18;8721:12;;;8714:40;8777:4;8820:11;;;8814:18;8855:42;8931:21;;;8917:12;;;8910:43;;;;8976:4;9024:11;;;9018:18;9014:27;;9000:12;;;8993:49;9065:4;9113:11;;;9107:18;9103:27;;;9089:12;;;9082:49;9154:4;9212:11;;;9206:18;9199:26;9192:34;9178:12;;;9171:56;9256:4;9247:14;;;;9284:15;;;;8563:1;8556:9;8527:782;;;-1:-1:-1;9326:3:1;;8023:1312;-1:-1:-1;;;;;;;8023:1312:1:o;9340:632::-;9511:2;9563:21;;;9633:13;;9536:18;;;9655:22;;;9482:4;;9511:2;9734:15;;;;9708:2;9693:18;;;9482:4;9777:169;9791:6;9788:1;9785:13;9777:169;;;9852:13;;9840:26;;9921:15;;;;9886:12;;;;9813:1;9806:9;9777:169;;;-1:-1:-1;9963:3:1;;9340:632;-1:-1:-1;;;;;;9340:632:1:o;10530:829::-;10641:6;10649;10657;10665;10673;10681;10689;10742:3;10730:9;10721:7;10717:23;10713:33;10710:53;;;10759:1;10756;10749:12;10710:53;10798:9;10785:23;10817:31;10842:5;10817:31;:::i;:::-;10867:5;-1:-1:-1;10924:2:1;10909:18;;10896:32;10937:33;10896:32;10937:33;:::i;:::-;10989:7;-1:-1:-1;11043:2:1;11028:18;;11015:32;;-1:-1:-1;11094:2:1;11079:18;;11066:32;;-1:-1:-1;11150:3:1;11135:19;;11122:33;11199:4;11186:18;;11174:31;;11164:59;;11219:1;11216;11209:12;11164:59;10530:829;;;;-1:-1:-1;10530:829:1;;;;11242:7;11296:3;11281:19;;11268:33;;-1:-1:-1;11348:3:1;11333:19;;;11320:33;;10530:829;-1:-1:-1;;10530:829:1:o;12900:714::-;13153:42;13145:6;13141:55;13130:9;13123:74;13233:6;13228:2;13217:9;13213:18;13206:34;13276:6;13271:2;13260:9;13256:18;13249:34;13319:3;13314:2;13303:9;13299:18;13292:31;13360:6;13354:3;13343:9;13339:19;13332:35;13418:6;13410;13404:3;13393:9;13389:19;13376:49;13475:1;13445:22;;;13469:3;13441:32;;;13434:43;;;;13529:2;13517:15;;;13534:66;13513:88;13498:104;13494:114;;12900:714;-1:-1:-1;;;;12900:714:1:o;13619:184::-;13689:6;13742:2;13730:9;13721:7;13717:23;13713:32;13710:52;;;13758:1;13755;13748:12;13710:52;-1:-1:-1;13781:16:1;;13619:184;-1:-1:-1;13619:184:1:o;13808:::-;13860:77;13857:1;13850:88;13957:4;13954:1;13947:15;13981:4;13978:1;13971:15;13997:125;14037:4;14065:1;14062;14059:8;14056:34;;;14070:18;;:::i;:::-;-1:-1:-1;14107:9:1;;13997:125::o;14459:228::-;14499:7;14625:1;14557:66;14553:74;14550:1;14547:81;14542:1;14535:9;14528:17;14524:105;14521:131;;;14632:18;;:::i;:::-;-1:-1:-1;14672:9:1;;14459:228::o;15417:242::-;15457:4;15486:30;15566:10;;;;15536;;15588:12;;;15585:38;;;15603:18;;:::i;:::-;15640:13;;15417:242;-1:-1:-1;;;15417:242:1:o;16211:184::-;16263:77;16260:1;16253:88;16360:4;16357:1;16350:15;16384:4;16381:1;16374:15;16400:112;16432:1;16458;16448:35;;16463:18;;:::i;:::-;-1:-1:-1;16497:9:1;;16400:112::o;16517:184::-;16569:77;16566:1;16559:88;16666:4;16663:1;16656:15;16690:4;16687:1;16680:15;16706:120;16746:1;16772;16762:35;;16777:18;;:::i;:::-;-1:-1:-1;16811:9:1;;16706:120::o;16831:249::-;16871:3;16899:30;16956:2;16953:1;16949:10;16986:2;16983:1;16979:10;17017:3;17013:2;17009:12;17004:3;17001:21;16998:47;;;17025:18;;:::i;:::-;17061:13;;16831:249;-1:-1:-1;;;;16831:249:1:o;17085:128::-;17125:3;17156:1;17152:6;17149:1;17146:13;17143:39;;;17162:18;;:::i;:::-;-1:-1:-1;17198:9:1;;17085:128::o;17552:184::-;17604:77;17601:1;17594:88;17701:4;17698:1;17691:15;17725:4;17722:1;17715:15;17741:195;17780:3;17811:66;17804:5;17801:77;17798:103;;17881:18;;:::i;:::-;-1:-1:-1;17928:1:1;17917:13;;17741:195::o;17941:251::-;18011:6;18064:2;18052:9;18043:7;18039:23;18035:32;18032:52;;;18080:1;18077;18070:12;18032:52;18112:9;18106:16;18131:31;18156:5;18131:31;:::i;20881:274::-;21010:3;21048:6;21042:13;21064:53;21110:6;21105:3;21098:4;21090:6;21086:17;21064:53;:::i;:::-;21133:16;;;;;20881:274;-1:-1:-1;;20881:274:1:o;21160:277::-;21227:6;21280:2;21268:9;21259:7;21255:23;21251:32;21248:52;;;21296:1;21293;21286:12;21248:52;21328:9;21322:16;21381:5;21374:13;21367:21;21360:5;21357:32;21347:60;;21403:1;21400;21393:12;22426:311;22466:7;22498:58;22583:2;22580:1;22576:10;22613:2;22610:1;22606:10;22669:3;22665:2;22661:12;22656:3;22653:21;22646:3;22639:11;22632:19;22628:47;22625:73;;;22678:18;;:::i;:::-;22718:13;;22426:311;-1:-1:-1;;;;22426:311:1:o;22742:240::-;22782:1;22808:58;22893:2;22890:1;22886:10;22915:3;22905:37;;22922:18;;:::i;:::-;22960:10;;22956:20;;;;;22742:240;-1:-1:-1;;22742:240:1:o
Swarm Source
ipfs://bdc5b014c6704437df24db228c555db8616bb6648c9811f54a9e45271265b6f5
Age | Block | Fee Address | BC Fee Address | Voting Power | Jailed | Incoming |
---|
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.