ERC-20
Overview
Max Total Supply
0.003329522197112017 ERC20 ***
Holders
5,444
Market
Price
$0.00 @ 0.000000 ETH
Onchain Market Cap
$0.00
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Balance
0.000000796197460517 ERC20 ***Value
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0xcc1c48ce...d21C7b009 The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
SyncSwapClassicPool
Compiler Version
v0.8.15+commit.e14f2714
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import "../../libraries/Math.sol"; import "../../libraries/ERC20Permit2.sol"; import "../../libraries/MetadataHelper.sol"; import "../../libraries/ReentrancyGuard.sol"; import "../../interfaces/ICallback.sol"; import "../../interfaces/vault/IVault.sol"; import "../../interfaces/pool/IClassicPool.sol"; import "../../interfaces/master/IPoolMaster.sol"; import "../../interfaces/master/IFeeRecipient.sol"; import "../../interfaces/factory/IPoolFactory.sol"; error Overflow(); error InsufficientLiquidityMinted(); contract SyncSwapClassicPool is IClassicPool, ERC20Permit2, ReentrancyGuard { using Math for uint; uint private constant MINIMUM_LIQUIDITY = 1000; uint private constant MAX_FEE = 1e5; /// @dev 100%. /// @dev Pool type `1` for classic pools. uint16 public constant override poolType = 1; address public immutable override master; address public immutable override vault; address public immutable override token0; address public immutable override token1; /// @dev Pool reserve of each pool token as of immediately after the most recent balance event. /// The value is used to measure growth in invariant on mints and input tokens on swaps. uint public override reserve0; uint public override reserve1; /// @dev Invariant of the pool as of immediately after the most recent liquidity event. /// The value is used to measure growth in invariant when protocol fee is enabled, /// and will be reset to zero if protocol fee is disabled. uint public override invariantLast; /// @dev Factory must ensures that the parameters are valid. constructor() { bytes memory _deployData = IPoolFactory(msg.sender).getDeployData(); (address _token0, address _token1) = abi.decode( _deployData, (address, address) ); address _master = IPoolFactory(msg.sender).master(); master = _master; vault = IPoolMaster(_master).vault(); (token0, token1) = (_token0, _token1); // try to set symbols for the LP token (bool _success0, string memory _symbol0) = MetadataHelper.getSymbol( _token0 ); (bool _success1, string memory _symbol1) = MetadataHelper.getSymbol( _token1 ); if (_success0 && _success1) { _initialize( string( abi.encodePacked( "SyncSwap ", _symbol0, "/", _symbol1, " Classic LP" ) ), string(abi.encodePacked(_symbol0, "/", _symbol1, " cSLP")) ); } else { _initialize("SyncSwap Classic LP", "cSLP"); } } function getAssets() external view override returns (address[] memory assets) { assets = new address[](2); assets[0] = token0; assets[1] = token1; } /// @dev Returns the verified sender address otherwise `address(0)`. function _getVerifiedSender( address _sender ) private view returns (address) { if (_sender != address(0)) { if (_sender != msg.sender) { if (!IPoolMaster(master).isForwarder(msg.sender)) { // The sender from non-forwarder is invalid. return address(0); } } } return _sender; } /// @dev Mints LP tokens - should be called via the router after transferring pool tokens. /// The router should ensure that sufficient LP tokens are minted. function mint( bytes calldata _data, address _sender, address _callback, bytes calldata _callbackData ) external override nonReentrant returns (uint) { ICallback.BaseMintCallbackParams memory params; params.to = abi.decode(_data, (address)); (params.reserve0, params.reserve1) = (reserve0, reserve1); (params.balance0, params.balance1) = _balances(); params.newInvariant = _computeInvariant( params.balance0, params.balance1 ); params.amount0 = params.balance0 - params.reserve0; params.amount1 = params.balance1 - params.reserve1; //require(_amount0 != 0 && _amount1 != 0); // Gets swap fee for the sender. _sender = _getVerifiedSender(_sender); uint _amount1Optimal = params.reserve0 == 0 ? 0 : Math.divUnsafeLast( (params.amount0 * params.reserve1), params.reserve0 ); bool _swap0For1 = params.amount1 < _amount1Optimal; if (_swap0For1) { params.swapFee = _getSwapFee(_sender, token0, token1); } else { params.swapFee = _getSwapFee(_sender, token1, token0); } // Adds mint fee to reserves (applies to invariant increase) if unbalanced. (params.fee0, params.fee1) = _unbalancedMintFee( params.swapFee, params.amount0, params.amount1, _amount1Optimal, params.reserve0, params.reserve1 ); params.reserve0 += params.fee0; params.reserve1 += params.fee1; // Calculates old invariant (where unbalanced fee added to) and, mint protocol fee if any. params.oldInvariant = _computeInvariant( params.reserve0, params.reserve1 ); bool _feeOn; (_feeOn, params.totalSupply) = _mintProtocolFee( 0, 0, params.oldInvariant ); if (params.totalSupply == 0) { params.liquidity = params.newInvariant - MINIMUM_LIQUIDITY; _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock on first mint. } else { // Calculates liquidity proportional to invariant growth. params.liquidity = ((params.newInvariant - params.oldInvariant) * params.totalSupply) / params.oldInvariant; } // Mints liquidity for recipient. if (params.liquidity == 0) { revert InsufficientLiquidityMinted(); } _mint(params.to, params.liquidity); // Calls callback with data. if (_callback != address(0)) { // Fills additional values for callback params. params.sender = _sender; params.callbackData = _callbackData; ICallback(_callback).syncSwapBaseMintCallback(params); } // Updates reserves and last invariant with new balances. _updateReserves(params.balance0, params.balance1); if (_feeOn) { invariantLast = params.newInvariant; } emit Mint( msg.sender, params.amount0, params.amount1, params.liquidity, params.to ); return params.liquidity; } /// @dev Burns LP tokens sent to this contract. /// The router should ensure that sufficient pool tokens are received. function burn( bytes calldata _data, address _sender, address _callback, bytes calldata _callbackData ) external override nonReentrant returns (TokenAmount[] memory _amounts) { ICallback.BaseBurnCallbackParams memory params; (params.to, params.withdrawMode) = abi.decode(_data, (address, uint8)); (params.balance0, params.balance1) = _balances(); params.liquidity = balanceOf[address(this)]; // Mints protocol fee if any. // Note `_mintProtocolFee` here will checks overflow. bool _feeOn; (_feeOn, params.totalSupply) = _mintProtocolFee( params.balance0, params.balance1, 0 ); // Calculates amounts of pool tokens proportional to balances. require(params.totalSupply != 0); params.amount0 = Math.divUnsafeLast( params.liquidity * params.balance0, params.totalSupply ); params.amount1 = Math.divUnsafeLast( params.liquidity * params.balance1, params.totalSupply ); //require(_amount0 != 0 || _amount1 != 0); // Burns liquidity and transfers pool tokens. _burn(address(this), params.liquidity); _transferTokens(token0, params.to, params.amount0, params.withdrawMode); _transferTokens(token1, params.to, params.amount1, params.withdrawMode); // Updates balances. /// @dev Cannot underflow because amounts are lesser figures derived from balances. unchecked { params.balance0 -= params.amount0; params.balance1 -= params.amount1; } // Calls callback with data. // Note reserves are not updated at this point to allow read the old values. if (_callback != address(0)) { // Fills additional values for callback params. params.sender = _getVerifiedSender(_sender); params.callbackData = _callbackData; ICallback(_callback).syncSwapBaseBurnCallback(params); } // Updates reserves and last invariant with up-to-date balances (after transfers). _updateReserves(params.balance0, params.balance1); if (_feeOn) { invariantLast = _computeInvariant(params.balance0, params.balance1); } _amounts = new TokenAmount[](2); _amounts[0] = TokenAmount(token0, params.amount0); _amounts[1] = TokenAmount(token1, params.amount1); emit Burn( msg.sender, params.amount0, params.amount1, params.liquidity, params.to ); } /// @dev Burns LP tokens sent to this contract and swaps one of the output tokens for another /// - i.e., the user gets a single token out by burning LP tokens. /// The router should ensure that sufficient pool tokens are received. function burnSingle( bytes calldata _data, address _sender, address _callback, bytes calldata _callbackData ) external override nonReentrant returns (TokenAmount memory _tokenAmount) { ICallback.BaseBurnSingleCallbackParams memory params; (params.tokenOut, params.to, params.withdrawMode) = abi.decode( _data, (address, address, uint8) ); (params.balance0, params.balance1) = _balances(); params.liquidity = balanceOf[address(this)]; // Mints protocol fee if any. // Note `_mintProtocolFee` here will checks overflow. bool _feeOn; (_feeOn, params.totalSupply) = _mintProtocolFee( params.balance0, params.balance1, 0 ); // Calculates amounts of pool tokens proportional to balances. require(params.totalSupply != 0); params.amount0 = Math.divUnsafeLast( params.liquidity * params.balance0, params.totalSupply ); params.amount1 = Math.divUnsafeLast( params.liquidity * params.balance1, params.totalSupply ); // Burns liquidity. _burn(address(this), params.liquidity); // Gets swap fee for the sender. _sender = _getVerifiedSender(_sender); // Swaps one token for another, transfers desired tokens, and update context values. /// @dev Calculate `amountOut` as if the user first withdrew balanced liquidity and then swapped from one token for another. if (params.tokenOut == token1) { // Swaps `token0` for `token1`. params.swapFee = _getSwapFee(_sender, token0, token1); params.tokenIn = token0; (params.amountSwapped, params.feeIn) = _getAmountOut( params.swapFee, params.amount0, params.balance0 - params.amount0, params.balance1 - params.amount1, true ); params.amount1 += params.amountSwapped; _transferTokens( token1, params.to, params.amount1, params.withdrawMode ); params.amountOut = params.amount1; params.amount0 = 0; params.balance1 -= params.amount1; } else { // Swaps `token1` for `token0`. require(params.tokenOut == token0); params.swapFee = _getSwapFee(_sender, token1, token0); params.tokenIn = token1; (params.amountSwapped, params.feeIn) = _getAmountOut( params.swapFee, params.amount1, params.balance0 - params.amount0, params.balance1 - params.amount1, false ); params.amount0 += params.amountSwapped; _transferTokens( token0, params.to, params.amount0, params.withdrawMode ); params.amountOut = params.amount0; params.amount1 = 0; params.balance0 -= params.amount0; } // Calls callback with data. // Note reserves are not updated at this point to allow read the old values. if (_callback != address(0)) { // Fills additional values for callback params. params.sender = _sender; params.callbackData = _callbackData; /// @dev Note the `tokenOut` parameter can be decided by the caller, and the correctness is not guaranteed. /// Additional checks MUST be performed in callback to ensure the `tokenOut` is one of the pools tokens if the sender /// is not a trusted source to avoid potential issues. ICallback(_callback).syncSwapBaseBurnSingleCallback(params); } // Update reserves and last invariant with up-to-date balances (updated above). _updateReserves(params.balance0, params.balance1); if (_feeOn) { invariantLast = _computeInvariant(params.balance0, params.balance1); } _tokenAmount = TokenAmount(params.tokenOut, params.amountOut); emit Burn( msg.sender, params.amount0, params.amount1, params.liquidity, params.to ); } /// @dev Swaps one token for another - should be called via the router after transferring input tokens. /// The router should ensure that sufficient output tokens are received. function swap( bytes calldata _data, address _sender, address _callback, bytes calldata _callbackData ) external override nonReentrant returns (TokenAmount memory _tokenAmount) { ICallback.BaseSwapCallbackParams memory params; (params.tokenIn, params.to, params.withdrawMode) = abi.decode( _data, (address, address, uint8) ); (params.reserve0, params.reserve1) = (reserve0, reserve1); (params.balance0, params.balance1) = _balances(); // Gets swap fee for the sender. _sender = _getVerifiedSender(_sender); // Calculates output amount, update context values and emit event. if (params.tokenIn == token0) { params.swapFee = _getSwapFee(_sender, token0, token1); params.tokenOut = token1; params.amountIn = params.balance0 - params.reserve0; (params.amountOut, params.feeIn) = _getAmountOut( params.swapFee, params.amountIn, params.reserve0, params.reserve1, true ); params.balance1 -= params.amountOut; emit Swap( msg.sender, params.amountIn, 0, 0, params.amountOut, params.to ); } else { require(params.tokenIn == token1); params.swapFee = _getSwapFee(_sender, token1, token0); params.tokenOut = token0; params.amountIn = params.balance1 - params.reserve1; (params.amountOut, params.feeIn) = _getAmountOut( params.swapFee, params.amountIn, params.reserve0, params.reserve1, false ); params.balance0 -= params.amountOut; emit Swap( msg.sender, 0, params.amountIn, params.amountOut, 0, params.to ); } // Checks overflow. if (params.balance0 > type(uint128).max) { revert Overflow(); } if (params.balance1 > type(uint128).max) { revert Overflow(); } // Transfers output tokens. _transferTokens( params.tokenOut, params.to, params.amountOut, params.withdrawMode ); // Calls callback with data. if (_callback != address(0)) { // Fills additional values for callback params. params.sender = _sender; params.callbackData = _callbackData; /// @dev Note the `tokenIn` parameter can be decided by the caller, and the correctness is not guaranteed. /// Additional checks MUST be performed in callback to ensure the `tokenIn` is one of the pools tokens if the sender /// is not a trusted source to avoid potential issues. ICallback(_callback).syncSwapBaseSwapCallback(params); } // Updates reserves with up-to-date balances (updated above). _updateReserves(params.balance0, params.balance1); _tokenAmount.token = params.tokenOut; _tokenAmount.amount = params.amountOut; } function _getSwapFee( address _sender, address _tokenIn, address _tokenOut ) private view returns (uint24 _swapFee) { _swapFee = getSwapFee(_sender, _tokenIn, _tokenOut, ""); } /// @dev This function doesn't check the forwarder. function getSwapFee( address _sender, address _tokenIn, address _tokenOut, bytes memory data ) public view override returns (uint24 _swapFee) { _swapFee = IPoolMaster(master).getSwapFee( address(this), _sender, _tokenIn, _tokenOut, data ); } function getProtocolFee() public view override returns (uint24 _protocolFee) { _protocolFee = IPoolMaster(master).getProtocolFee(address(this)); } function _updateReserves(uint _balance0, uint _balance1) private { (reserve0, reserve1) = (_balance0, _balance1); emit Sync(_balance0, _balance1); } function _transferTokens( address token, address to, uint amount, uint8 withdrawMode ) private { if (withdrawMode == 0) { IVault(vault).transfer(token, to, amount); } else { IVault(vault).withdrawAlternative(token, to, amount, withdrawMode); } } function _balances() private view returns (uint balance0, uint balance1) { balance0 = IVault(vault).balanceOf(token0, address(this)); balance1 = IVault(vault).balanceOf(token1, address(this)); } /// @dev This fee is charged to cover for the swap fee when users adding unbalanced liquidity. function _unbalancedMintFee( uint _swapFee, uint _amount0, uint _amount1, uint _amount1Optimal, uint _reserve0, uint _reserve1 ) private pure returns (uint _token0Fee, uint _token1Fee) { if (_reserve0 == 0) { return (0, 0); } if (_amount1 >= _amount1Optimal) { _token1Fee = Math.divUnsafeLast( (_swapFee * (_amount1 - _amount1Optimal)), (2 * MAX_FEE) ); } else { uint _amount0Optimal = (_amount1 * _reserve0) / _reserve1; _token0Fee = Math.divUnsafeLast( (_swapFee * (_amount0 - _amount0Optimal)), (2 * MAX_FEE) ); } } function _mintProtocolFee( uint _reserve0, uint _reserve1, uint _invariant ) private returns (bool _feeOn, uint _totalSupply) { _totalSupply = totalSupply; address _feeRecipient = IPoolMaster(master).getFeeRecipient(); _feeOn = (_feeRecipient != address(0)); uint _invariantLast = invariantLast; if (_invariantLast != 0) { if (_feeOn) { if (_invariant == 0) { _invariant = _computeInvariant(_reserve0, _reserve1); } if (_invariant > _invariantLast) { /// @dev Mints `protocolFee` % of growth in liquidity (invariant). uint _protocolFee = getProtocolFee(); uint _numerator = _totalSupply * (_invariant - _invariantLast) * _protocolFee; uint _denominator = (MAX_FEE - _protocolFee) * _invariant + _protocolFee * _invariantLast; uint _liquidity = _numerator / _denominator; if (_liquidity != 0) { _mint(_feeRecipient, _liquidity); // Notifies the fee recipient. IFeeRecipient(_feeRecipient).notifyFees( 1, address(this), _liquidity, _protocolFee, "" ); _totalSupply += _liquidity; // update cached value. } } } else { /// @dev Resets last invariant to clear measured growth if protocol fee is not enabled. invariantLast = 0; } } } function getReserves() external view override returns (uint _reserve0, uint _reserve1) { (_reserve0, _reserve1) = (reserve0, reserve1); } function getAmountOut( address _tokenIn, uint _amountIn, address _sender ) external view override returns (uint _amountOut) { (uint _reserve0, uint _reserve1) = (reserve0, reserve1); bool _swap0For1 = _tokenIn == token0; address _tokenOut = _swap0For1 ? token1 : token0; (_amountOut, ) = _getAmountOut( _getSwapFee(_sender, _tokenIn, _tokenOut), _amountIn, _reserve0, _reserve1, _swap0For1 ); } function getAmountIn( address _tokenOut, uint _amountOut, address _sender ) external view override returns (uint _amountIn) { (uint _reserve0, uint _reserve1) = (reserve0, reserve1); bool _swap1For0 = _tokenOut == token0; address _tokenIn = _swap1For0 ? token1 : token0; _amountIn = _getAmountIn( _getSwapFee(_sender, _tokenIn, _tokenOut), _amountOut, _reserve0, _reserve1, _swap1For0 ); } function _getAmountOut( uint _swapFee, uint _amountIn, uint _reserve0, uint _reserve1, bool _token0In ) private pure returns (uint _dy, uint _feeIn) { if (_amountIn == 0) { _dy = 0; } else { uint _amountInWithFee = _amountIn * (MAX_FEE - _swapFee); _feeIn = Math.divUnsafeLast(_amountIn * _swapFee, MAX_FEE); if (_token0In) { _dy = (_amountInWithFee * _reserve1) / (_reserve0 * MAX_FEE + _amountInWithFee); } else { _dy = (_amountInWithFee * _reserve0) / (_reserve1 * MAX_FEE + _amountInWithFee); } } } function _getAmountIn( uint _swapFee, uint _amountOut, uint _reserve0, uint _reserve1, bool _token0Out ) private pure returns (uint _dx) { if (_amountOut == 0) { _dx = 0; } else { if (_token0Out) { _dx = (_reserve1 * _amountOut * MAX_FEE) / ((_reserve0 - _amountOut) * (MAX_FEE - _swapFee)) + 1; } else { _dx = (_reserve0 * _amountOut * MAX_FEE) / ((_reserve1 - _amountOut) * (MAX_FEE - _swapFee)) + 1; } } } function _computeInvariant( uint _reserve0, uint _reserve1 ) private pure returns (uint _invariant) { if (_reserve0 > type(uint128).max) { revert Overflow(); } if (_reserve1 > type(uint128).max) { revert Overflow(); } _invariant = (_reserve0 * _reserve1).sqrt(); } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IPoolFactory { function master() external view returns (address); function getDeployData() external view returns (bytes memory); function createPool(bytes calldata data) external returns (address pool); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; /// @dev The callback interface for SyncSwap base pool operations. /// Note additional checks will be required for some callbacks, see below for more information. /// Visit the documentation https://syncswap.gitbook.io/api-documentation/ for more details. interface ICallback { struct BaseMintCallbackParams { address sender; address to; uint reserve0; uint reserve1; uint balance0; uint balance1; uint amount0; uint amount1; uint fee0; uint fee1; uint newInvariant; uint oldInvariant; uint totalSupply; uint liquidity; uint24 swapFee; bytes callbackData; } function syncSwapBaseMintCallback(BaseMintCallbackParams calldata params) external; struct BaseBurnCallbackParams { address sender; address to; uint balance0; uint balance1; uint liquidity; uint totalSupply; uint amount0; uint amount1; uint8 withdrawMode; bytes callbackData; } function syncSwapBaseBurnCallback(BaseBurnCallbackParams calldata params) external; struct BaseBurnSingleCallbackParams { address sender; address to; address tokenIn; address tokenOut; uint balance0; uint balance1; uint liquidity; uint totalSupply; uint amount0; uint amount1; uint amountOut; uint amountSwapped; uint feeIn; uint24 swapFee; uint8 withdrawMode; bytes callbackData; } /// @dev Note the `tokenOut` parameter can be decided by the caller, and the correctness is not guaranteed. /// Additional checks MUST be performed in callback to ensure the `tokenOut` is one of the pools tokens if the sender /// is not a trusted source to avoid potential issues. function syncSwapBaseBurnSingleCallback(BaseBurnSingleCallbackParams calldata params) external; struct BaseSwapCallbackParams { address sender; address to; address tokenIn; address tokenOut; uint reserve0; uint reserve1; uint balance0; uint balance1; uint amountIn; uint amountOut; uint feeIn; uint24 swapFee; uint8 withdrawMode; bytes callbackData; } /// @dev Note the `tokenIn` parameter can be decided by the caller, and the correctness is not guaranteed. /// Additional checks MUST be performed in callback to ensure the `tokenIn` is one of the pools tokens if the sender /// is not a trusted source to avoid potential issues. function syncSwapBaseSwapCallback(BaseSwapCallbackParams calldata params) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; /// @notice The manager contract to control fees. /// Management functions are omitted. interface IFeeManager { function getSwapFee( address pool, address sender, address tokenIn, address tokenOut, bytes calldata data) external view returns (uint24); function getProtocolFee(address pool) external view returns (uint24); function getFeeRecipient() external view returns (address); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IFeeRecipient { /// @dev Notifies the fee recipient after sent fees. function notifyFees( uint16 feeType, address token, uint amount, uint feeRate, bytes calldata data ) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IForwarderRegistry { function isForwarder(address forwarder) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IFeeManager.sol"; import "./IForwarderRegistry.sol"; /// @dev The master contract to create pools and manage whitelisted factories. /// Inheriting the fee manager interface to support fee queries. interface IPoolMaster is IFeeManager, IForwarderRegistry { event SetFactoryWhitelisted(address indexed factory, bool whitelisted); event RegisterPool( address indexed factory, address indexed pool, uint16 indexed poolType, bytes data ); event UpdateForwarderRegistry(address indexed newForwarderRegistry); event UpdateFeeManager(address indexed newFeeManager); function vault() external view returns (address); function feeManager() external view returns (address); function pools(uint) external view returns (address); function poolsLength() external view returns (uint); // Forwarder Registry function setForwarderRegistry(address) external; // Fees function setFeeManager(address) external; // Factories function isFactoryWhitelisted(address) external view returns (bool); function setFactoryWhitelisted(address factory, bool whitelisted) external; // Pools function isPool(address) external view returns (bool); function getPool(bytes32) external view returns (address); function createPool(address factory, bytes calldata data) external returns (address pool); function registerPool(address pool, uint16 poolType, bytes calldata data) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IPool.sol"; import "../token/IERC20Permit2.sol"; interface IBasePool is IPool, IERC20Permit2 { function token0() external view returns (address); function token1() external view returns (address); function reserve0() external view returns (uint); function reserve1() external view returns (uint); function invariantLast() external view returns (uint); function getReserves() external view returns (uint, uint); function getAmountOut(address tokenIn, uint amountIn, address sender) external view returns (uint amountOut); function getAmountIn(address tokenOut, uint amountOut, address sender) external view returns (uint amountIn); event Mint( address indexed sender, uint amount0, uint amount1, uint liquidity, address indexed to ); event Burn( address indexed sender, uint amount0, uint amount1, uint liquidity, address indexed to ); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync( uint reserve0, uint reserve1 ); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IBasePool.sol"; interface IClassicPool is IBasePool { }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IPool { struct TokenAmount { address token; uint amount; } /// @dev Returns the address of pool master. function master() external view returns (address); /// @dev Returns the vault. function vault() external view returns (address); /// @dev Returns the pool type. function poolType() external view returns (uint16); /// @dev Returns the assets of the pool. function getAssets() external view returns (address[] memory assets); /// @dev Returns the swap fee of the pool. function getSwapFee(address sender, address tokenIn, address tokenOut, bytes calldata data) external view returns (uint24 swapFee); /// @dev Returns the protocol fee of the pool. function getProtocolFee() external view returns (uint24 protocolFee); /// @dev Mints liquidity. function mint( bytes calldata data, address sender, address callback, bytes calldata callbackData ) external returns (uint liquidity); /// @dev Burns liquidity. function burn( bytes calldata data, address sender, address callback, bytes calldata callbackData ) external returns (TokenAmount[] memory tokenAmounts); /// @dev Burns liquidity with single output token. function burnSingle( bytes calldata data, address sender, address callback, bytes calldata callbackData ) external returns (TokenAmount memory tokenAmount); /// @dev Swaps between tokens. function swap( bytes calldata data, address sender, address callback, bytes calldata callbackData ) external returns (TokenAmount memory tokenAmount); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IERC165 { /// @notice Query if a contract implements an interface /// @param interfaceID The interface identifier, as specified in ERC-165 /// @dev Interface identification is specified in ERC-165. This function /// uses less than 30,000 gas. /// @return `true` if the contract implements `interfaceID` and /// `interfaceID` is not 0xffffffff, `false` otherwise function supportsInterface(bytes4 interfaceID) external view returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IERC20Base.sol"; interface IERC20 is IERC20Base { function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IERC20Base { 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 amount) external returns (bool); function transfer(address to, uint amount) external returns (bool); function transferFrom(address from, address to, uint amount) external returns (bool); event Approval(address indexed owner, address indexed spender, uint amount); event Transfer(address indexed from, address indexed to, uint amount); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IERC20.sol"; interface IERC20Permit is IERC20 { function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; function nonces(address owner) external view returns (uint); function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IERC20Permit.sol"; interface IERC20Permit2 is IERC20Permit { function permit2(address owner, address spender, uint amount, uint deadline, bytes calldata signature) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; interface IERC3156FlashBorrower { /** * @dev Receive a flash loan. * @param initiator The initiator of the loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @param fee The additional amount of tokens to repay. * @param data Arbitrary data structure, intended to contain user-defined parameters. * @return The keccak256 hash of "ERC3156FlashBorrower.onFlashLoan" */ function onFlashLoan( address initiator, address token, uint256 amount, uint256 fee, bytes calldata data ) external returns (bytes32); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IERC3156FlashBorrower.sol"; interface IERC3156FlashLender { /** * @dev The amount of currency available to be lent. * @param token The loan currency. * @return The amount of `token` that can be borrowed. */ function maxFlashLoan( address token ) external view returns (uint256); /** * @dev The fee to be charged for a given loan. * @param token The loan currency. * @param amount The amount of tokens lent. * @return The amount of `token` to be charged for the loan, on top of the returned principal. */ function flashFee( address token, uint256 amount ) external view returns (uint256); /** * @dev Initiate a flash loan. * @param receiver The receiver of the tokens in the loan, and the receiver of the callback. * @param token The loan currency. * @param amount The amount of tokens lent. * @param data Arbitrary data structure, intended to contain user-defined parameters. */ function flashLoan( IERC3156FlashBorrower receiver, address token, uint256 amount, bytes calldata data ) external returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IFlashLoanRecipient.sol"; import "./IERC3156FlashLender.sol"; interface IFlashLoan is IERC3156FlashLender { function flashLoanFeePercentage() external view returns (uint); /** * @dev Performs a 'flash loan', sending tokens to `recipient`, executing the `receiveFlashLoan` hook on it, * and then reverting unless the tokens plus a proportional protocol fee have been returned. * * The `tokens` and `amounts` arrays must have the same length, and each entry in these indicates the loan amount * for each token contract. `tokens` must be sorted in ascending order. * * The 'userData' field is ignored by the Vault, and forwarded as-is to `recipient` as part of the * `receiveFlashLoan` call. * * Emits `FlashLoan` events. */ function flashLoanMultiple( IFlashLoanRecipient recipient, address[] memory tokens, uint[] memory amounts, bytes memory userData ) external; /** * @dev Emitted for each individual flash loan performed by `flashLoan`. */ event FlashLoan(address indexed recipient, address indexed token, uint amount, uint feeAmount); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity >=0.7.0 <0.9.0; // Inspired by Aave Protocol's IFlashLoanReceiver. interface IFlashLoanRecipient { /** * @dev When `flashLoan` is called on the Vault, it invokes the `receiveFlashLoan` hook on the recipient. * * At the time of the call, the Vault will have transferred `amounts` for `tokens` to the recipient. Before this * call returns, the recipient must have transferred `amounts` plus `feeAmounts` for each token back to the * Vault, or else the entire flash loan will revert. * * `userData` is the same value passed in the `IVault.flashLoan` call. */ function receiveFlashLoan( address[] memory tokens, uint[] memory amounts, uint[] memory feeAmounts, bytes memory userData ) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IFlashLoan.sol"; interface IVault is IFlashLoan { function wETH() external view returns (address); function reserves(address token) external view returns (uint reserve); function balanceOf(address token, address owner) external view returns (uint balance); function deposit(address token, address to) external payable returns (uint amount); function depositETH(address to) external payable returns (uint amount); function transferAndDeposit(address token, address to, uint amount) external payable returns (uint); function transfer(address token, address to, uint amount) external; function withdraw(address token, address to, uint amount) external; function withdrawAlternative(address token, address to, uint amount, uint8 mode) external; function withdrawETH(address to, uint amount) external; }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. * * Based on OpenZeppelin's ECDSA library. * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/561d1061fc568f04c7a65853538e834a889751e8/contracts/utils/cryptography/ECDSA.sol */ library ECDSA { /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { // Check the signature length if (signature.length != 65) { return address(0); } // Divide the signature in r, s and v variables bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly // solhint-disable-next-line no-inline-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return address(0); } return ecrecover(hash, v, r, s); } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import "../interfaces/token/IERC165.sol"; import "../interfaces/token/IERC20Permit2.sol"; import "./SignatureChecker.sol"; error Expired(); error InvalidSignature(); /** * @dev A simple ERC20 implementation for pool's liquidity token, supports permit by both ECDSA signatures from * externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like Argent. * * Based on Solmate's ERC20. * https://github.com/transmissions11/solmate/blob/bff24e835192470ed38bf15dbed6084c2d723ace/src/tokens/ERC20.sol */ contract ERC20Permit2 is IERC165, IERC20Permit2 { uint8 public immutable override decimals = 18; uint public override totalSupply; mapping(address => uint) public override balanceOf; mapping(address => mapping(address => uint)) public override allowance; bytes32 private constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9; // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)") mapping(address => uint) public override nonces; // These members are actually immutable as // `_initialize` will only indent to be called once. string public override name; string public override symbol; uint private INITIAL_CHAIN_ID; bytes32 private INITIAL_DOMAIN_SEPARATOR; function _initialize(string memory _name, string memory _symbol) internal { name = _name; symbol = _symbol; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = _computeDomainSeparator(); } function supportsInterface(bytes4 interfaceID) external pure override returns (bool) { return interfaceID == this.supportsInterface.selector || // ERC-165 interfaceID == this.permit.selector || // ERC-2612 interfaceID == this.permit2.selector; // Permit2 } function DOMAIN_SEPARATOR() public view override returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : _computeDomainSeparator(); } function _computeDomainSeparator() private view returns (bytes32) { return keccak256( abi.encode( // keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)") 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f, keccak256(bytes(name)), // keccak256(bytes("1")) 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6, block.chainid, address(this) ) ); } function _approve(address _owner, address _spender, uint _amount) private { allowance[_owner][_spender] = _amount; emit Approval(_owner, _spender, _amount); } function approve(address _spender, uint _amount) public override returns (bool) { _approve(msg.sender, _spender, _amount); return true; } function transfer(address _to, uint _amount) public override returns (bool) { balanceOf[msg.sender] -= _amount; // Cannot overflow because the sum of all user balances can't exceed the max uint256 value. unchecked { balanceOf[_to] += _amount; } emit Transfer(msg.sender, _to, _amount); return true; } function transferFrom(address _from, address _to, uint _amount) public override returns (bool) { uint256 _allowed = allowance[_from][msg.sender]; // Saves gas for limited approvals. if (_allowed != type(uint).max) { allowance[_from][msg.sender] = _allowed - _amount; } balanceOf[_from] -= _amount; // Cannot overflow because the sum of all user balances can't exceed the max uint256 value. unchecked { balanceOf[_to] += _amount; } emit Transfer(_from, _to, _amount); return true; } function _mint(address _to, uint _amount) internal { totalSupply += _amount; // Cannot overflow because the sum of all user balances can't exceed the max uint256 value. unchecked { balanceOf[_to] += _amount; } emit Transfer(address(0), _to, _amount); } function _burn(address _from, uint _amount) internal { balanceOf[_from] -= _amount; // Cannot underflow because a user's balance will never be larger than the total supply. unchecked { totalSupply -= _amount; } emit Transfer(_from, address(0), _amount); } modifier ensures(uint _deadline) { // solhint-disable-next-line not-rely-on-time if (block.timestamp > _deadline) { revert Expired(); } _; } function _permitHash( address _owner, address _spender, uint _amount, uint _deadline ) private returns (bytes32) { return keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256(abi.encode(PERMIT_TYPEHASH, _owner, _spender, _amount, nonces[_owner]++, _deadline)) ) ); } function permit( address _owner, address _spender, uint _amount, uint _deadline, uint8 _v, bytes32 _r, bytes32 _s ) public override ensures(_deadline) { bytes32 _hash = _permitHash(_owner, _spender, _amount, _deadline); address _recoveredAddress = ecrecover(_hash, _v, _r, _s); if (_recoveredAddress != _owner) { revert InvalidSignature(); } if (_recoveredAddress == address(0)) { revert InvalidSignature(); } _approve(_owner, _spender, _amount); } function permit2( address _owner, address _spender, uint _amount, uint _deadline, bytes calldata _signature ) public override ensures(_deadline) { bytes32 _hash = _permitHash(_owner, _spender, _amount, _deadline); if (!SignatureChecker.isValidSignatureNow(_owner, _hash, _signature)) { revert InvalidSignature(); } _approve(_owner, _spender, _amount); } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; /// @dev Math functions. /// @dev Modified from Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/FixedPointMathLib.sol) library Math { /// @notice Compares a and b and returns 'true' if the difference between a and b /// is less than 1 or equal to each other. /// @param a uint256 to compare with. /// @param b uint256 to compare with. function within1(uint256 a, uint256 b) internal pure returns (bool) { unchecked { if (a > b) { return a - b <= 1; } return b - a <= 1; } } /// @dev Returns the square root of `x`. function sqrt(uint256 x) internal pure returns (uint256 z) { /// @solidity memory-safe-assembly assembly { // `floor(sqrt(2**15)) = 181`. `sqrt(2**15) - 181 = 2.84`. z := 181 // The "correct" value is 1, but this saves a multiplication later. // This segment is to get a reasonable initial estimate for the Babylonian method. With a bad // start, the correct # of bits increases ~linearly each iteration instead of ~quadratically. // Let `y = x / 2**r`. // We check `y >= 2**(k + 8)` but shift right by `k` bits // each branch to ensure that if `x >= 256`, then `y >= 256`. let r := shl(7, lt(0xffffffffffffffffffffffffffffffffff, x)) r := or(r, shl(6, lt(0xffffffffffffffffff, shr(r, x)))) r := or(r, shl(5, lt(0xffffffffff, shr(r, x)))) r := or(r, shl(4, lt(0xffffff, shr(r, x)))) z := shl(shr(1, r), z) // Goal was to get `z*z*y` within a small factor of `x`. More iterations could // get y in a tighter range. Currently, we will have y in `[256, 256*(2**16))`. // We ensured `y >= 256` so that the relative difference between `y` and `y+1` is small. // That's not possible if `x < 256` but we can just verify those cases exhaustively. // Now, `z*z*y <= x < z*z*(y+1)`, and `y <= 2**(16+8)`, and either `y >= 256`, or `x < 256`. // Correctness can be checked exhaustively for `x < 256`, so we assume `y >= 256`. // Then `z*sqrt(y)` is within `sqrt(257)/sqrt(256)` of `sqrt(x)`, or about 20bps. // For `s` in the range `[1/256, 256]`, the estimate `f(s) = (181/1024) * (s+1)` // is in the range `(1/2.84 * sqrt(s), 2.84 * sqrt(s))`, // with largest error when `s = 1` and when `s = 256` or `1/256`. // Since `y` is in `[256, 256*(2**16))`, let `a = y/65536`, so that `a` is in `[1/256, 256)`. // Then we can estimate `sqrt(y)` using // `sqrt(65536) * 181/1024 * (a + 1) = 181/4 * (y + 65536)/65536 = 181 * (y + 65536)/2**18`. // There is no overflow risk here since `y < 2**136` after the first branch above. z := shr(18, mul(z, add(shr(r, x), 65536))) // A `mul()` is saved from starting `z` at 181. // Given the worst case multiplicative error of 2.84 above, 7 iterations should be enough. z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) z := shr(1, add(z, div(x, z))) // If `x+1` is a perfect square, the Babylonian method cycles between // `floor(sqrt(x))` and `ceil(sqrt(x))`. This statement ensures we return floor. // See: https://en.wikipedia.org/wiki/Integer_square_root#Using_only_integer_division // Since the ceil is rare, we save gas on the assignment and repeat division in the rare case. // If you don't care whether the floor or ceil square root is returned, you can remove this statement. z := sub(z, lt(div(x, z), z)) } } // Mul Div /// @dev Rounded down. function mulDiv( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } /// @dev Rounded down. /// This function assumes that `x` is not zero, and must be checked externally. function mulDivUnsafeFirst( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x * y) / x == y) if iszero(and(iszero(iszero(denominator)), eq(div(z, x), y))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } /// @dev Rounded down. /// This function assumes that `denominator` is not zero, and must be checked externally. function mulDivUnsafeLast( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(x == 0 || (x * y) / x == y) if iszero(or(iszero(x), eq(div(z, x), y))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } /// @dev Rounded down. /// This function assumes that both `x` and `denominator` are not zero, and must be checked externally. function mulDivUnsafeFirstLast( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require((x * y) / x == y) if iszero(eq(div(z, x), y)) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } // Mul /// @dev Optimized safe multiplication operation for minimal gas cost. /// Equivalent to * function mul( uint256 x, uint256 y ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(x == 0 || (x * y) / x == y) if iszero(or(iszero(x), eq(div(z, x), y))) { revert(0, 0) } } } /// @dev Optimized unsafe multiplication operation for minimal gas cost. /// This function assumes that `x` is not zero, and must be checked externally. function mulUnsafeFirst( uint256 x, uint256 y ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require((x * y) / x == y) if iszero(eq(div(z, x), y)) { revert(0, 0) } } } // Div /// @dev Optimized safe division operation for minimal gas cost. /// Equivalent to / function div( uint256 x, uint256 y ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := div(x, y) // Equivalent to require(y != 0) if iszero(y) { revert(0, 0) } } } /// @dev Optimized unsafe division operation for minimal gas cost. /// Division by 0 will not reverts and returns 0, and must be checked externally. function divUnsafeLast( uint256 x, uint256 y ) internal pure returns (uint256 z) { assembly { z := div(x, y) } } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; library MetadataHelper { /** * @dev Returns symbol of the token. * * @param token The address of a ERC20 token. * * Return boolean indicating the status and the symbol as string; * * NOTE: Symbol is not the standard interface and some tokens may not support it. * Calling against these tokens will not success, with an empty result. */ function getSymbol(address token) internal view returns (bool, string memory) { // bytes4(keccak256(bytes("symbol()"))) (bool success, bytes memory returndata) = token.staticcall(abi.encodeWithSelector(0x95d89b41)); if (success) { return (true, abi.decode(returndata, (string))); } else { return (false, ""); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import "./ECDSA.sol"; /** * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like * Argent and Gnosis Safe. * * Based on OpenZeppelin's SignatureChecker library. * https://github.com/OpenZeppelin/openzeppelin-contracts/blob/561d1061fc568f04c7a65853538e834a889751e8/contracts/utils/cryptography/SignatureChecker.sol */ library SignatureChecker { bytes4 constant internal MAGICVALUE = 0x1626ba7e; // bytes4(keccak256("isValidSignature(bytes32,bytes)") /** * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`. * * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus * change through time. It could return true at block N and false at block N+1 (or the opposite). */ function isValidSignatureNow( address signer, bytes32 hash, bytes memory signature ) internal view returns (bool) { (address recovered) = ECDSA.recover(hash, signature); if (recovered == signer) { if (recovered != address(0)) { return true; } } (bool success, bytes memory result) = signer.staticcall( abi.encodeWithSelector(MAGICVALUE, hash, signature) ); return ( success && result.length == 32 && abi.decode(result, (bytes32)) == bytes32(MAGICVALUE) ); } }
{ "optimizer": { "enabled": true, "runs": 200, "details": { "yul": false } }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"Expired","type":"error"},{"inputs":[],"name":"InsufficientLiquidityMinted","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"Overflow","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","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":false,"internalType":"uint256","name":"liquidity","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Burn","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":false,"internalType":"uint256","name":"liquidity","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"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":"uint256","name":"reserve0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reserve1","type":"uint256"}],"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":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":"_amount","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":"bytes","name":"_data","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_callback","type":"address"},{"internalType":"bytes","name":"_callbackData","type":"bytes"}],"name":"burn","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IPool.TokenAmount[]","name":"_amounts","type":"tuple[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_callback","type":"address"},{"internalType":"bytes","name":"_callbackData","type":"bytes"}],"name":"burnSingle","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IPool.TokenAmount","name":"_tokenAmount","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"uint256","name":"_amountOut","type":"uint256"},{"internalType":"address","name":"_sender","type":"address"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"_amountIn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"uint256","name":"_amountIn","type":"uint256"},{"internalType":"address","name":"_sender","type":"address"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"_amountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAssets","outputs":[{"internalType":"address[]","name":"assets","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getProtocolFee","outputs":[{"internalType":"uint24","name":"_protocolFee","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint256","name":"_reserve0","type":"uint256"},{"internalType":"uint256","name":"_reserve1","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"getSwapFee","outputs":[{"internalType":"uint24","name":"_swapFee","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"invariantLast","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"master","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_callback","type":"address"},{"internalType":"bytes","name":"_callbackData","type":"bytes"}],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"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":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","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":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"permit2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"poolType","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve0","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reserve1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceID","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes","name":"_data","type":"bytes"},{"internalType":"address","name":"_sender","type":"address"},{"internalType":"address","name":"_callback","type":"address"},{"internalType":"bytes","name":"_callbackData","type":"bytes"}],"name":"swap","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct IPool.TokenAmount","name":"_tokenAmount","type":"tuple"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","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":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
61012060405260126080523480156200001757600080fd5b5060016008819055506000336001600160a01b031663d039f6226040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000061573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200008b919081019062000597565b905060008082806020019051810190620000a6919062000611565b915091506000336001600160a01b031663ee97f7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000111919062000654565b9050806001600160a01b031660a0816001600160a01b031681525050806001600160a01b031663fbfa77cf6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200016c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000192919062000654565b6001600160a01b0390811660c05282811661010052831660e052600080620001c685620002c2602090811b6200210017901c565b91509150600080620001e386620002c260201b620021001760201c565b91509150838015620001f25750815b1562000251576200024b8382604051602001620002119291906200069e565b604051602081830303815290604052848360405160200162000235929190620006f3565b60408051601f198184030181529190526200039a565b620002b4565b620002b46040518060400160405280601381526020017f53796e635377617020436c6173736963204c500000000000000000000000000081525060405180604001604052806004815260200163063534c560e41b8152506200039a60201b60201c565b505050505050505062000a13565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b1790529051600091606091839182916001600160a01b038716916200030c9162000730565b600060405180830381855afa9150503d806000811462000349576040519150601f19603f3d011682016040523d82523d6000602084013e6200034e565b606091505b509150915081156200037d5760018180602001905181019062000372919062000597565b935093505050915091565b600060405180602001604052806000815250935093505050915091565b6004620003a8838262000842565b506005620003b7828262000842565b5046600655620003c6620003cd565b6007555050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60046040516200040191906200098c565b6040519081900381206200043f92917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69046903090602001620009bd565b60405160208183030381529060405280519060200120905090565b634e487b7160e01b600052604160045260246000fd5b601f19601f83011681018181106001600160401b03821117156200049857620004986200045a565b6040525050565b6000620004ab60405190565b9050620004b9828262000470565b919050565b60006001600160401b03821115620004da57620004da6200045a565b601f19601f83011660200192915050565b60005b8381101562000508578181015183820152602001620004ee565b8381111562000518576000848401525b50505050565b6000620005356200052f84620004be565b6200049f565b905082815260208101848484011115620005525762000552600080fd5b6200055f848285620004eb565b509392505050565b600082601f8301126200057d576200057d600080fd5b81516200058f8482602086016200051e565b949350505050565b600060208284031215620005ae57620005ae600080fd5b81516001600160401b03811115620005c957620005c9600080fd5b6200058f8482850162000567565b60006001600160a01b0382165b92915050565b620005f581620005d7565b81146200060157600080fd5b50565b8051620005e481620005ea565b60008060408385031215620006295762000629600080fd5b600062000637858562000604565b92505060206200064a8582860162000604565b9150509250929050565b6000602082840312156200066b576200066b600080fd5b60006200058f848462000604565b600062000684825190565b62000694818560208601620004eb565b9290920192915050565b68029bcb731a9bbb0b8160bd1b81526009016000620006be828562000679565b602f60f81b81526001019150620006d6828462000679565b6a020436c6173736963204c560ac1b81529150600b82016200058f565b600062000701828562000679565b602f60f81b8152600101915062000719828462000679565b6402063534c560dc1b81529150600582016200058f565b60006200073e828462000679565b9392505050565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806200077057607f821691505b60208210810362000785576200078562000745565b50919050565b6000620005e4620007998381565b90565b620007a7836200078b565b81546008840282811b60001990911b908116901990911617825550505050565b6000620007d68184846200079c565b505050565b81811015620007fa57620007f1600082620007c7565b600101620007db565b5050565b601f821115620007d6576000818152602090206020601f85010481016020851015620008275750805b6200083b6020601f860104830182620007db565b5050505050565b81516001600160401b038111156200085e576200085e6200045a565b6200086a82546200075b565b62000877828285620007fe565b6020601f831160018114620008ae5760008415620008955750858201515b600019600886021c19811660028602178655506200090a565b600085815260208120601f198616915b82811015620008e05788850151825560209485019460019092019101620008be565b86831015620008fd5784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b6000815462000921816200075b565b6001821680156200093b5760018114620009515762000983565b60ff198316865281151582028601935062000983565b60008581526020902060005b838110156200097b578154888201526001909101906020016200095d565b838801955050505b50505092915050565b60006200073e828462000912565b620009a5816200078b565b82525050565b80620009a5565b620009a581620005d7565b60a08101620009cd82886200099a565b620009dc6020830187620009ab565b620009eb60408301866200099a565b620009fa6060830185620009ab565b62000a096080830184620009b2565b9695505050505050565b60805160a05160c05160e0516101005161418162000b8c6000396000818161042e015281816106fd0152818161073701528181610d4201528181610da401528181610e6801528181610f1401528181610f700152818161130f015281816114da01528181611513015281816115fe01528181611644015281816119fb01528181611db701528181611fa3015281816120b501526122fc015260008181610288015281816106dc0152818161075801528181610d8301528181610ddf01528181610ece01528181610f3501528181610ffd015281816112bb01528181611478015281816114b9015281816116650152818161169e0152818161199f015281816119d501528181611d7e01528181611f43015281816120590152818161208f01526122370152600081816104da01528181612208015281816122cf015281816129ea0152612a71015260008181610493015281816118ff01528181611a5f0152818161249001526125d40152600061030d01526141816000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c806370a082311161010f578063b1dd61b6116100a2578063ee97f7f311610071578063ee97f7f31461048e578063f66eab5b146104b5578063fbfa77cf146104d5578063ff9c8ac6146104fc57600080fd5b8063b1dd61b614610414578063d21220a714610429578063d505accf14610450578063dd62ed3e1461046357600080fd5b806395d89b41116100de57806395d89b41146103de578063a287c795146103e6578063a5a41031146103f9578063a9059cbb1461040157600080fd5b806370a082311461036b5780637132bb7f1461038b5780637ecebe001461039e5780638b4c5470146103be57600080fd5b806323b872dd116101875780633644e515116101565780633644e5151461033c578063443cb4bc146103445780635a76f25e1461034d57806367e4ac2c1461035657600080fd5b806323b872dd146102c057806327b0bcea146102d35780632c0198cc146102f3578063313ce5671461030857600080fd5b80630902f1ac116101c35780630902f1ac1461025c578063095ea7b3146102705780630dfe16811461028357806318160ddd146102b757600080fd5b806301ffc9a7146101f557806303e7286a1461021e57806306fdde031461023e57806307f293f714610253575b600080fd5b610208610203366004612ee1565b61050f565b6040516102159190612f0c565b60405180910390f35b61023161022c366004612f91565b610561565b6040516102159190613038565b610246610a1a565b60405161021591906130a4565b610231600b5481565b600954600a546040516102159291906130b5565b61020861027e3660046130e1565b610aa8565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516102159190613127565b61023160005481565b6102086102ce366004613135565b610abe565b6102e66102e1366004612f91565b610b9e565b60405161021591906131a9565b6103066103013660046131b7565b6111d5565b005b61032f7f000000000000000000000000000000000000000000000000000000000000000081565b604051610215919061323b565b61023161127a565b61023160095481565b610231600a5481565b61035e611299565b60405161021591906132a6565b6102316103793660046132b7565b60016020526000908152604090205481565b6102e6610399366004612f91565b611364565b6102316103ac3660046132b7565b60036020526000908152604090205481565b6103d16103cc3660046133d3565b6118e5565b604051610215919061345d565b610246611986565b6102316103f436600461346b565b611993565b6103d1611a45565b61020861040f3660046130e1565b611ad5565b61041c600181565b60405161021591906134bb565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b61030661045e3660046134dd565b611b4a565b61023161047136600461357c565b600260209081526000928352604080842090915290825290205481565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b6104c86104c3366004612f91565b611c3f565b6040516102159190613601565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b61023161050a36600461346b565b61204d565b60006001600160e01b031982166301ffc9a760e01b148061054057506001600160e01b0319821663d505accf60e01b145b8061055b57506001600160e01b03198216630b00663360e21b145b92915050565b600061056b6121d1565b61060260405180610200016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001606081525090565b61060e878901896132b7565b6001600160a01b03166020820152600954600a5460608301526040820152610634612203565b60a083018190526080830182905261064c919061236d565b610140820152604081015160808201516106669190613628565b60c0820152606081015160a082015161067f9190613628565b60e082015261068d86612458565b9550600081604001516000146106c3576106be82606001518360c001516106b4919061363f565b8360400151900490565b6106c6565b60005b60e08301519091508111801561073157610721887f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101c0840152610788565b61077c887f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101c08401525b6107b0836101c0015162ffffff168460c001518560e00151858760400151886060015161253b565b61012085015261010084018190526040840180516107cf90839061365e565b9052506101208301516060840180516107e990839061365e565b90525060408301516060840151610800919061236d565b610160840181905260009061081890829081906125c8565b6101808601819052909150600003610855576103e884610140015161083d9190613628565b6101a085015261085060006103e86127a1565b61088d565b610160840151610180850151610140860151610872908390613628565b61087c919061363f565b610886919061368c565b6101a08501525b836101a001516000036108b357604051633489be7560e21b815260040160405180910390fd5b6108c68460200151856101a001516127a1565b6001600160a01b0388161561097a576001600160a01b0389168452604080516020601f89018190048102820181019092528781529088908890819084018382808284376000920191909152505050506101e0850152604051630204997360e41b81526001600160a01b038916906320499730906109479087906004016137e7565b600060405180830381600087803b15801561096157600080fd5b505af1158015610975573d6000803e3d6000fd5b505050505b61098c84608001518560a001516127fe565b801561099c57610140840151600b555b83602001516001600160a01b0316336001600160a01b03167fa8137fff86647d8a402117b9c5dbda627f721d3773338fb9678c83e54ed390808660c001518760e00151886101a001516040516109f4939291906137f8565b60405180910390a35050506101a001519050610a106001600855565b9695505050505050565b60048054610a2790613836565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5390613836565b8015610aa05780601f10610a7557610100808354040283529160200191610aa0565b820191906000526020600020905b815481529060010190602001808311610a8357829003601f168201915b505050505081565b6000610ab5338484612846565b50600192915050565b6001600160a01b03831660009081526002602090815260408083203384529091528120546000198114610b1a57610af58382613628565b6001600160a01b03861660009081526002602090815260408083203384529091529020555b6001600160a01b03851660009081526001602052604081208054859290610b42908490613628565b90915550506001600160a01b038085166000818152600160205260409081902080548701905551909187169060008051602061412c83398151915290610b89908790613038565b60405180910390a360019150505b9392505050565b6040805180820190915260008082526020820152610bba6121d1565b610c6660405180610200016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b610c7287890189613862565b60ff166101c08401526001600160a01b039081166020840152166060820152610c99612203565b60a08301908152608083019182523060009081526001602052604081205460c085015291519051610ccb9190836125c8565b60e08401819052909150600003610ce157600080fd5b610d0282608001518360c00151610cf8919061363f565b8360e00151900490565b61010083015260a082015160c0830151610d1f91610cf89161363f565b61012083015260c0820151610d359030906128ae565b610d3e87612458565b96507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682606001516001600160a01b031603610ecc57610dc8877f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101a083018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408401526101008301516080840151610e3c929190610e20908290613628565b8561012001518660a00151610e359190613628565b600161290d565b610180840152610160830181905261012083018051610e5c90839061365e565b91508181525050610e9d7f00000000000000000000000000000000000000000000000000000000000000008360200151846101200151856101c001516129c8565b6101208201516101408301819052600061010084015260a083018051610ec4908390613628565b90525061105d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682606001516001600160a01b031614610f0e57600080fd5b610f59877f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101a083018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408401526101208301516101008401516080850151610fd1939291610fb591613628565b8561012001518660a00151610fca9190613628565b600061290d565b610180840152610160830181905261010083018051610ff190839061365e565b915081815250506110327f00000000000000000000000000000000000000000000000000000000000000008360200151846101000151856101c001516129c8565b61010082015161014083018190526000610120840152608083018051611059908390613628565b9052505b6001600160a01b03861615611111576001600160a01b0387168252604080516020601f87018190048102820181019092528581529086908690819084018382808284376000920191909152505050506101e0830152604051630eace54160e11b81526001600160a01b03871690631d59ca82906110de9085906004016139d5565b600060405180830381600087803b1580156110f857600080fd5b505af115801561110c573d6000803e3d6000fd5b505050505b61112382608001518360a001516127fe565b801561113f5761113b82608001518360a0015161236d565b600b555b604051806040016040528083606001516001600160a01b03168152602001836101400151815250925081602001516001600160a01b0316336001600160a01b03167fd175a80c109434bb89948928ab2475a6647c94244cb70002197896423c8833638461010001518561012001518660c001516040516111c1939291906137f8565b60405180910390a35050610a106001600855565b82804211156111f757604051630407b05b60e31b815260040160405180910390fd5b600061120588888888612ae0565b9050611248888286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b9992505050565b61126557604051638baa579f60e01b815260040160405180910390fd5b611270888888612846565b5050505050505050565b600060065446146112925761128d612cc5565b905090565b5060075490565b60408051600280825260608083018452926020830190803683370190505090507f0000000000000000000000000000000000000000000000000000000000000000816000815181106112ed576112ed6139e6565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600181518110611341576113416139e6565b60200260200101906001600160a01b031690816001600160a01b03168152505090565b60408051808201909152600080825260208201526113806121d1565b61141e604051806101c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b61142a87890189613862565b60ff166101808401526001600160a01b039081166020840152166040820152600954600a5460a08301526080820152611461612203565b60e083015260c082015261147486612458565b95507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681604001516001600160a01b0316036115fc576114fe867f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101608201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166060820152608081015160c082015161154c9190613628565b8161010001818152505061157b81610160015162ffffff1682610100015183608001518460a00151600161290d565b610140830152610120820181905260e08201805161159a908390613628565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822926115ef926000918291613a14565b60405180910390a3611785565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681604001516001600160a01b03161461163e57600080fd5b611689867f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101608201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016606082015260a081015160e08201516116d79190613628565b8161010001818152505061170681610160015162ffffff1682610100015183608001518460a00151600061290d565b610140830152610120820181905260c082018051611725908390613628565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229261177c9260009291908390613a49565b60405180910390a35b60c08101516001600160801b0310156117b157604051631a93c68960e11b815260040160405180910390fd5b60e08101516001600160801b0310156117dd57604051631a93c68960e11b815260040160405180910390fd5b6117fb816060015182602001518361012001518461018001516129c8565b6001600160a01b038516156118af576001600160a01b0386168152604080516020601f86018190048102820181019092528481529085908590819084018382808284376000920191909152505050506101a082015260405163608dbcbb60e01b81526001600160a01b0386169063608dbcbb9061187c908490600401613b9b565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050505b6118c18160c001518260e001516127fe565b60608101516001600160a01b0316825261012001516020820152610a106001600855565b604051634625a94d60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690634625a94d9061193c9030908990899089908990600401613bac565b602060405180830381865afa158015611959573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197d9190613c09565b95945050505050565b60058054610a2790613836565b600954600a54600091907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b039081169087161483816119f9577f0000000000000000000000000000000000000000000000000000000000000000611a1b565b7f00000000000000000000000000000000000000000000000000000000000000005b9050611a39611a2b87838b612516565b62ffffff1688868686612d4e565b98975050505050505050565b6040516302a64b8360e21b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630a992e0c90611a94903090600401613127565b602060405180830381865afa158015611ab1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128d9190613c09565b33600090815260016020526040812080548391908390611af6908490613628565b90915550506001600160a01b0383166000818152600160205260409081902080548501905551339060008051602061412c83398151915290611b39908690613038565b60405180910390a350600192915050565b8380421115611b6c57604051630407b05b60e31b815260040160405180910390fd5b6000611b7a89898989612ae0565b9050600060018287878760405160008152602001604052604051611ba19493929190613c2a565b6020604051602081039080840390855afa158015611bc3573d6000803e3d6000fd5b505050602060405103519050896001600160a01b0316816001600160a01b031614611c0157604051638baa579f60e01b815260040160405180910390fd5b6001600160a01b038116611c2857604051638baa579f60e01b815260040160405180910390fd5b611c338a8a8a612846565b50505050505050505050565b6060611c496121d1565b611cb460405180610140016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600060ff168152602001606081525090565b611cc087890189613c52565b60ff166101008301526001600160a01b03166020820152611cdf612203565b606083019081526040808401928352306000908152600160205290812054608085015291519051611d119190836125c8565b60a08401819052909150600003611d2757600080fd5b611d4882604001518360800151611d3e919061363f565b8360a00151900490565b60c083015260608201516080830151611d6491611d3e9161363f565b60e08301526080820151611d799030906128ae565b611db27f000000000000000000000000000000000000000000000000000000000000000083602001518460c001518561010001516129c8565b611deb7f000000000000000000000000000000000000000000000000000000000000000083602001518460e001518561010001516129c8565b60c082015160408301805191909103905260e08201516060830180519190910390526001600160a01b03861615611ec957611e2587612458565b6001600160a01b03168252604080516020601f870181900481028201810190925285815290869086908190840183828082843760009201919091525050505061012083015260405163109ea27d60e31b81526001600160a01b038716906384f513e890611e96908590600401613d4e565b600060405180830381600087803b158015611eb057600080fd5b505af1158015611ec4573d6000803e3d6000fd5b505050505b611edb826040015183606001516127fe565b8015611ef757611ef38260400151836060015161236d565b600b555b6040805160028082526060820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081611f0d57905050925060405180604001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018360c0015181525083600081518110611f8b57611f8b6139e6565b602002602001018190525060405180604001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018360e0015181525083600181518110611feb57611feb6139e6565b602002602001018190525081602001516001600160a01b0316336001600160a01b03167fd175a80c109434bb89948928ab2475a6647c94244cb70002197896423c8833638460c001518560e0015186608001516040516111c1939291906137f8565b600954600a54600091907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b039081169087161483816120b3577f00000000000000000000000000000000000000000000000000000000000000006120d5565b7f00000000000000000000000000000000000000000000000000000000000000005b90506120f36120e5878a84612516565b62ffffff168886868661290d565b5098975050505050505050565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b1790529051600091606091839182916001600160a01b0387169161214891613d81565b600060405180830381855afa9150503d8060008114612183576040519150601f19603f3d011682016040523d82523d6000602084013e612188565b606091505b509150915081156121b4576001818060200190518101906121a99190613de5565b935093505050915091565b600060405180602001604052806000815250935093505050915091565b6002600854036121fc5760405162461bcd60e51b81526004016121f390613e20565b60405180910390fd5b6002600855565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f7888aec7f0000000000000000000000000000000000000000000000000000000000000000306040518363ffffffff1660e01b8152600401612274929190613e5b565b602060405180830381865afa158015612291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b59190613e81565b604051633de222bb60e21b81529092506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90612326907f0000000000000000000000000000000000000000000000000000000000000000903090600401613e5b565b602060405180830381865afa158015612343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123679190613e81565b90509091565b60006001600160801b0383111561239757604051631a93c68960e11b815260040160405180910390fd5b6001600160801b038211156123bf57604051631a93c68960e11b815260040160405180910390fd5b610b976123cc838561363f565b70ffffffffffffffffffffffffffffffffff811160071b81811c68ffffffffffffffffff1060061b1781811c64ffffffffff1060051b1781811c62ffffff1060041b1781811c620100000160b5600192831c1b0260121c80830401811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b60006001600160a01b03821615612512576001600160a01b038216331461251257604051632af3bd5560e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063abcef554906124c5903390600401613127565b602060405180830381865afa1580156124e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125069190613eb5565b61251257506000919050565b5090565b6000612533848484604051806020016040528060008152506118e5565b949350505050565b60008083600003612551575060009050806125bd565b848610612589576125826125658688613628565b61256f908a61363f565b61257d620186a0600261363f565b900490565b90506125bd565b600083612596868961363f565b6125a0919061368c565b90506125b96125af828a613628565b61256f908b61363f565b9250505b965096945050505050565b600080600054905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634ccb20c06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612630573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126549190613ee1565b600b546001600160a01b038216151594509091508015612797578315612791578460000361268957612686878761236d565b94505b8085111561278c57600061269b611a45565b62ffffff1690506000816126af8489613628565b6126b9908761363f565b6126c3919061363f565b905060006126d1848461363f565b886126df85620186a0613628565b6126e9919061363f565b6126f3919061365e565b90506000612701828461368c565b905080156127875761271386826127a1565b604051631087d04360e31b81526001600160a01b0387169063843e82189061274690600190309086908a90600401613f17565b600060405180830381600087803b15801561276057600080fd5b505af1158015612774573d6000803e3d6000fd5b505050508087612784919061365e565b96505b505050505b612797565b6000600b555b5050935093915050565b806000808282546127b2919061365e565b90915550506001600160a01b0382166000818152600160205260408082208054850190555160008051602061412c833981519152906127f2908590613038565b60405180910390a35050565b600a81905560098290556040517fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a9061283a90849084906130b5565b60405180910390a15050565b6001600160a01b0380841660008181526002602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906128a1908590613038565b60405180910390a3505050565b6001600160a01b038216600090815260016020526040812080548392906128d6908490613628565b90915550506000805482900381556040516001600160a01b0384169060008051602061412c833981519152906127f2908590613038565b6000808560000361292157600091506129be565b600061293088620186a0613628565b61293a908861363f565b9050612952612949898961363f565b620186a0900490565b9150831561298d5780612968620186a08861363f565b612972919061365e565b61297c868361363f565b612986919061368c565b92506129bc565b8061299b620186a08761363f565b6129a5919061365e565b6129af878361363f565b6129b9919061368c565b92505b505b9550959350505050565b8060ff16600003612a5a576040516317d5759960e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063beabacc890612a2390879087908790600401613f61565b600060405180830381600087803b158015612a3d57600080fd5b505af1158015612a51573d6000803e3d6000fd5b50505050612ada565b604051636cb568c160e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636cb568c190612aac908790879087908790600401613f7c565b600060405180830381600087803b158015612ac657600080fd5b505af1158015611270573d6000803e3d6000fd5b50505050565b6000612aea61127a565b6001600160a01b038616600090815260036020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c992899289928992909190612b3883613fb1565b9190505587604051602001612b5296959493929190613fcb565b60405160208183030381529060405280519060200120604051602001612b7992919061401a565b604051602081830303815290604052805190602001209050949350505050565b600080612ba68484612e09565b9050846001600160a01b0316816001600160a01b031603612bda576001600160a01b03811615612bda576001915050610b97565b600080866001600160a01b0316631626ba7e60e01b8787604051602401612c0292919061404b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612c409190613d81565b600060405180830381855afa9150503d8060008114612c7b576040519150601f19603f3d011682016040523d82523d6000602084013e612c80565b606091505b5091509150818015612c93575080516020145b8015612cba57508051630b135d3f60e11b90612cb89083016020908101908401613e81565b145b979650505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6004604051612cf791906140dd565b604051908190038120612d3392917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc690469030906020016140e9565b60405160208183030381529060405280519060200120905090565b600084600003612d605750600061197d565b8115612dbb57612d7386620186a0613628565b612d7d8686613628565b612d87919061363f565b620186a0612d95878661363f565b612d9f919061363f565b612da9919061368c565b612db490600161365e565b905061197d565b612dc886620186a0613628565b612dd28685613628565b612ddc919061363f565b620186a0612dea878761363f565b612df4919061363f565b612dfe919061368c565b610a1090600161365e565b60008151604114612e1c5750600061055b565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612e62576000935050505061055b565b60018682858560405160008152602001604052604051612e859493929190613c2a565b6020604051602081039080840390855afa158015612ea7573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b6001600160e01b031981165b8114612ed357600080fd5b50565b803561055b81612ebc565b600060208284031215612ef657612ef6600080fd5b60006125338484612ed6565b8015155b82525050565b6020810161055b8284612f02565b60008083601f840112612f2f57612f2f600080fd5b50813567ffffffffffffffff811115612f4a57612f4a600080fd5b602083019150836001820283011115612f6557612f65600080fd5b9250929050565b60006001600160a01b03821661055b565b612ec881612f6c565b803561055b81612f7d565b60008060008060008060808789031215612fad57612fad600080fd5b863567ffffffffffffffff811115612fc757612fc7600080fd5b612fd389828a01612f1a565b96509650506020612fe689828a01612f86565b9450506040612ff789828a01612f86565b935050606087013567ffffffffffffffff81111561301757613017600080fd5b61302389828a01612f1a565b92509250509295509295509295565b80612f06565b6020810161055b8284613032565b60005b83811015613061578181015183820152602001613049565b83811115612ada5750506000910152565b600061307c825190565b808452602084019350613093818560208601613046565b601f01601f19169290920192915050565b60208082528101610b978184613072565b604081016130c38285613032565b610b976020830184613032565b80612ec8565b803561055b816130d0565b600080604083850312156130f7576130f7600080fd5b60006131038585612f86565b9250506020613114858286016130d6565b9150509250929050565b612f0681612f6c565b6020810161055b828461311e565b60008060006060848603121561314d5761314d600080fd5b60006131598686612f86565b935050602061316a86828701612f86565b925050604061317b868287016130d6565b9150509250925092565b80516040830190613196848261311e565b506020820151612ada6020850182613032565b6040810161055b8284613185565b60008060008060008060a087890312156131d3576131d3600080fd5b60006131df8989612f86565b96505060206131f089828a01612f86565b955050604061320189828a016130d6565b945050606061321289828a016130d6565b935050608087013567ffffffffffffffff81111561301757613017600080fd5b60ff8116612f06565b6020810161055b8284613232565b6000613255838361311e565b505060200190565b6000613267825190565b80845260209384019383018060005b8381101561329b57815161328a8882613249565b975060208301925050600101613276565b509495945050505050565b60208082528101610b97818461325d565b6000602082840312156132cc576132cc600080fd5b60006125338484612f86565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff82111715613314576133146132d8565b6040525050565b600061332660405190565b905061333282826132ee565b919050565b600067ffffffffffffffff821115613351576133516132d8565b601f19601f83011660200192915050565b82818337506000910152565b600061338161337c84613337565b61331b565b90508281526020810184848401111561339c5761339c600080fd5b6133a7848285613362565b509392505050565b600082601f8301126133c3576133c3600080fd5b813561253384826020860161336e565b600080600080608085870312156133ec576133ec600080fd5b60006133f88787612f86565b945050602061340987828801612f86565b935050604061341a87828801612f86565b925050606085013567ffffffffffffffff81111561343a5761343a600080fd5b613446878288016133af565b91505092959194509250565b62ffffff8116612f06565b6020810161055b8284613452565b60008060006060848603121561348357613483600080fd5b600061348f8686612f86565b93505060206134a0868287016130d6565b925050604061317b86828701612f86565b61ffff8116612f06565b6020810161055b82846134b1565b60ff8116612ec8565b803561055b816134c9565b600080600080600080600060e0888a0312156134fb576134fb600080fd5b60006135078a8a612f86565b97505060206135188a828b01612f86565b96505060406135298a828b016130d6565b955050606061353a8a828b016130d6565b945050608061354b8a828b016134d2565b93505060a061355c8a828b016130d6565b92505060c061356d8a828b016130d6565b91505092959891949750929550565b6000806040838503121561359257613592600080fd5b600061359e8585612f86565b925050602061311485828601612f86565b60006135bb8383613185565b505060400190565b60006135cd825190565b80845260209384019383018060005b8381101561329b5781516135f088826135af565b9750602083019250506001016135dc565b60208082528101610b9781846135c3565b634e487b7160e01b600052601160045260246000fd5b60008282101561363a5761363a613612565b500390565b600081600019048311821515161561365957613659613612565b500290565b6000821982111561367157613671613612565b500190565b634e487b7160e01b600052601260045260246000fd5b60008261369b5761369b613676565b500490565b80516000906102008401906136b5858261311e565b5060208301516136c8602086018261311e565b5060408301516136db6040860182613032565b5060608301516136ee6060860182613032565b5060808301516137016080860182613032565b5060a083015161371460a0860182613032565b5060c083015161372760c0860182613032565b5060e083015161373a60e0860182613032565b5061010083015161374f610100860182613032565b50610120830151613764610120860182613032565b50610140830151613779610140860182613032565b5061016083015161378e610160860182613032565b506101808301516137a3610180860182613032565b506101a08301516137b86101a0860182613032565b506101c08301516137cd6101c0860182613452565b506101e08301518482036101e086015261197d8282613072565b60208082528101610b9781846136a0565b606081016138068286613032565b6138136020830185613032565b6125336040830184613032565b634e487b7160e01b600052602260045260246000fd5b60028104600182168061384a57607f821691505b60208210810361385c5761385c613820565b50919050565b60008060006060848603121561387a5761387a600080fd5b60006138868686612f86565b935050602061389786828701612f86565b925050604061317b868287016134d2565b80516000906102008401906138bd858261311e565b5060208301516138d0602086018261311e565b5060408301516138e3604086018261311e565b5060608301516138f6606086018261311e565b5060808301516139096080860182613032565b5060a083015161391c60a0860182613032565b5060c083015161392f60c0860182613032565b5060e083015161394260e0860182613032565b50610100830151613957610100860182613032565b5061012083015161396c610120860182613032565b50610140830151613981610140860182613032565b50610160830151613996610160860182613032565b506101808301516139ab610180860182613032565b506101a08301516139c06101a0860182613452565b506101c08301516137cd6101c0860182613232565b60208082528101610b9781846138a8565b634e487b7160e01b600052603260045260246000fd5b600061055b613a088381565b90565b612f06816139fc565b60808101613a228287613032565b613a2f6020830186613a0b565b613a3c6040830185613a0b565b61197d6060830184613032565b60808101613a578287613a0b565b613a646020830186613032565b613a716040830185613032565b61197d6060830184613a0b565b80516000906101c0840190613a93858261311e565b506020830151613aa6602086018261311e565b506040830151613ab9604086018261311e565b506060830151613acc606086018261311e565b506080830151613adf6080860182613032565b5060a0830151613af260a0860182613032565b5060c0830151613b0560c0860182613032565b5060e0830151613b1860e0860182613032565b50610100830151613b2d610100860182613032565b50610120830151613b42610120860182613032565b50610140830151613b57610140860182613032565b50610160830151613b6c610160860182613452565b50610180830151613b81610180860182613232565b506101a08301518482036101a086015261197d8282613072565b60208082528101610b978184613a7e565b60a08101613bba828861311e565b613bc7602083018761311e565b613bd4604083018661311e565b613be1606083018561311e565b8181036080830152612cba8184613072565b62ffffff8116612ec8565b805161055b81613bf3565b600060208284031215613c1e57613c1e600080fd5b60006125338484613bfe565b60808101613c388287613032565b613c456020830186613232565b613a3c6040830185613032565b60008060408385031215613c6857613c68600080fd5b6000613c748585612f86565b9250506020613114858286016134d2565b8051600090610140840190613c9a858261311e565b506020830151613cad602086018261311e565b506040830151613cc06040860182613032565b506060830151613cd36060860182613032565b506080830151613ce66080860182613032565b5060a0830151613cf960a0860182613032565b5060c0830151613d0c60c0860182613032565b5060e0830151613d1f60e0860182613032565b50610100830151613d34610100860182613232565b5061012083015184820361012086015261197d8282613072565b60208082528101610b978184613c85565b6000613d69825190565b613d77818560208601613046565b9290920192915050565b6000610b978284613d5f565b6000613d9b61337c84613337565b905082815260208101848484011115613db657613db6600080fd5b6133a7848285613046565b600082601f830112613dd557613dd5600080fd5b8151612533848260208601613d8d565b600060208284031215613dfa57613dfa600080fd5b815167ffffffffffffffff811115613e1457613e14600080fd5b61253384828501613dc1565b6020808252810161055b81601f81527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00602082015260400190565b60408101613e69828561311e565b610b97602083018461311e565b805161055b816130d0565b600060208284031215613e9657613e96600080fd5b60006125338484613e76565b801515612ec8565b805161055b81613ea2565b600060208284031215613eca57613eca600080fd5b60006125338484613eaa565b805161055b81612f7d565b600060208284031215613ef657613ef6600080fd5b60006125338484613ed6565b600061ffff821661055b565b612f0681613f02565b60a08101613f258287613f0e565b613f32602083018661311e565b613f3f6040830185613032565b613f4c6060830184613032565b81810360808301526000815260208101610a10565b60608101613f6f828661311e565b613813602083018561311e565b60808101613f8a828761311e565b613f97602083018661311e565b613fa46040830185613032565b61197d6060830184613232565b60006000198203613fc457613fc4613612565b5060010190565b60c08101613fd98289613032565b613fe6602083018861311e565b613ff3604083018761311e565b6140006060830186613032565b61400d6080830185613032565b612cba60a0830184613032565b61190160f01b815260020160006140318285613032565b6020820191506140418284613032565b5060200192915050565b604081016140598285613032565b81810360208301526125338184613072565b6000815461407881613836565b60018216801561408f57600181146140a4576140d4565b60ff19831686528115158202860193506140d4565b60008581526020902060005b838110156140cc578154888201526001909101906020016140b0565b838801955050505b50505092915050565b6000610b97828461406b565b60a081016140f78288613a0b565b6141046020830187613032565b6141116040830186613a0b565b61411e6060830185613032565b610a10608083018461311e56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212209d4df6080488c965e85c8d46a748d3e9c678e134194f5c0fad6ef2903c78217b64736f6c634300080f0033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101f05760003560e01c806370a082311161010f578063b1dd61b6116100a2578063ee97f7f311610071578063ee97f7f31461048e578063f66eab5b146104b5578063fbfa77cf146104d5578063ff9c8ac6146104fc57600080fd5b8063b1dd61b614610414578063d21220a714610429578063d505accf14610450578063dd62ed3e1461046357600080fd5b806395d89b41116100de57806395d89b41146103de578063a287c795146103e6578063a5a41031146103f9578063a9059cbb1461040157600080fd5b806370a082311461036b5780637132bb7f1461038b5780637ecebe001461039e5780638b4c5470146103be57600080fd5b806323b872dd116101875780633644e515116101565780633644e5151461033c578063443cb4bc146103445780635a76f25e1461034d57806367e4ac2c1461035657600080fd5b806323b872dd146102c057806327b0bcea146102d35780632c0198cc146102f3578063313ce5671461030857600080fd5b80630902f1ac116101c35780630902f1ac1461025c578063095ea7b3146102705780630dfe16811461028357806318160ddd146102b757600080fd5b806301ffc9a7146101f557806303e7286a1461021e57806306fdde031461023e57806307f293f714610253575b600080fd5b610208610203366004612ee1565b61050f565b6040516102159190612f0c565b60405180910390f35b61023161022c366004612f91565b610561565b6040516102159190613038565b610246610a1a565b60405161021591906130a4565b610231600b5481565b600954600a546040516102159291906130b5565b61020861027e3660046130e1565b610aa8565b6102aa7f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c681565b6040516102159190613127565b61023160005481565b6102086102ce366004613135565b610abe565b6102e66102e1366004612f91565b610b9e565b60405161021591906131a9565b6103066103013660046131b7565b6111d5565b005b61032f7f000000000000000000000000000000000000000000000000000000000000001281565b604051610215919061323b565b61023161127a565b61023160095481565b610231600a5481565b61035e611299565b60405161021591906132a6565b6102316103793660046132b7565b60016020526000908152604090205481565b6102e6610399366004612f91565b611364565b6102316103ac3660046132b7565b60036020526000908152604090205481565b6103d16103cc3660046133d3565b6118e5565b604051610215919061345d565b610246611986565b6102316103f436600461346b565b611993565b6103d1611a45565b61020861040f3660046130e1565b611ad5565b61041c600181565b60405161021591906134bb565b6102aa7f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f81565b61030661045e3660046134dd565b611b4a565b61023161047136600461357c565b600260209081526000928352604080842090915290825290205481565b6102aa7f000000000000000000000000608cb7c3168427091f5994a45baf12083964b4a381565b6104c86104c3366004612f91565b611c3f565b6040516102159190613601565b6102aa7f0000000000000000000000007160570bb153edd0ea1775ec2b2ac9b65f1ab61b81565b61023161050a36600461346b565b61204d565b60006001600160e01b031982166301ffc9a760e01b148061054057506001600160e01b0319821663d505accf60e01b145b8061055b57506001600160e01b03198216630b00663360e21b145b92915050565b600061056b6121d1565b61060260405180610200016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001606081525090565b61060e878901896132b7565b6001600160a01b03166020820152600954600a5460608301526040820152610634612203565b60a083018190526080830182905261064c919061236d565b610140820152604081015160808201516106669190613628565b60c0820152606081015160a082015161067f9190613628565b60e082015261068d86612458565b9550600081604001516000146106c3576106be82606001518360c001516106b4919061363f565b8360400151900490565b6106c6565b60005b60e08301519091508111801561073157610721887f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c67f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f612516565b62ffffff166101c0840152610788565b61077c887f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f7f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c6612516565b62ffffff166101c08401525b6107b0836101c0015162ffffff168460c001518560e00151858760400151886060015161253b565b61012085015261010084018190526040840180516107cf90839061365e565b9052506101208301516060840180516107e990839061365e565b90525060408301516060840151610800919061236d565b610160840181905260009061081890829081906125c8565b6101808601819052909150600003610855576103e884610140015161083d9190613628565b6101a085015261085060006103e86127a1565b61088d565b610160840151610180850151610140860151610872908390613628565b61087c919061363f565b610886919061368c565b6101a08501525b836101a001516000036108b357604051633489be7560e21b815260040160405180910390fd5b6108c68460200151856101a001516127a1565b6001600160a01b0388161561097a576001600160a01b0389168452604080516020601f89018190048102820181019092528781529088908890819084018382808284376000920191909152505050506101e0850152604051630204997360e41b81526001600160a01b038916906320499730906109479087906004016137e7565b600060405180830381600087803b15801561096157600080fd5b505af1158015610975573d6000803e3d6000fd5b505050505b61098c84608001518560a001516127fe565b801561099c57610140840151600b555b83602001516001600160a01b0316336001600160a01b03167fa8137fff86647d8a402117b9c5dbda627f721d3773338fb9678c83e54ed390808660c001518760e00151886101a001516040516109f4939291906137f8565b60405180910390a35050506101a001519050610a106001600855565b9695505050505050565b60048054610a2790613836565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5390613836565b8015610aa05780601f10610a7557610100808354040283529160200191610aa0565b820191906000526020600020905b815481529060010190602001808311610a8357829003601f168201915b505050505081565b6000610ab5338484612846565b50600192915050565b6001600160a01b03831660009081526002602090815260408083203384529091528120546000198114610b1a57610af58382613628565b6001600160a01b03861660009081526002602090815260408083203384529091529020555b6001600160a01b03851660009081526001602052604081208054859290610b42908490613628565b90915550506001600160a01b038085166000818152600160205260409081902080548701905551909187169060008051602061412c83398151915290610b89908790613038565b60405180910390a360019150505b9392505050565b6040805180820190915260008082526020820152610bba6121d1565b610c6660405180610200016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b610c7287890189613862565b60ff166101c08401526001600160a01b039081166020840152166060820152610c99612203565b60a08301908152608083019182523060009081526001602052604081205460c085015291519051610ccb9190836125c8565b60e08401819052909150600003610ce157600080fd5b610d0282608001518360c00151610cf8919061363f565b8360e00151900490565b61010083015260a082015160c0830151610d1f91610cf89161363f565b61012083015260c0820151610d359030906128ae565b610d3e87612458565b96507f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f6001600160a01b031682606001516001600160a01b031603610ecc57610dc8877f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c67f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f612516565b62ffffff166101a083018190526001600160a01b037f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c61660408401526101008301516080840151610e3c929190610e20908290613628565b8561012001518660a00151610e359190613628565b600161290d565b610180840152610160830181905261012083018051610e5c90839061365e565b91508181525050610e9d7f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f8360200151846101200151856101c001516129c8565b6101208201516101408301819052600061010084015260a083018051610ec4908390613628565b90525061105d565b7f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c66001600160a01b031682606001516001600160a01b031614610f0e57600080fd5b610f59877f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f7f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c6612516565b62ffffff166101a083018190526001600160a01b037f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f1660408401526101208301516101008401516080850151610fd1939291610fb591613628565b8561012001518660a00151610fca9190613628565b600061290d565b610180840152610160830181905261010083018051610ff190839061365e565b915081815250506110327f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c68360200151846101000151856101c001516129c8565b61010082015161014083018190526000610120840152608083018051611059908390613628565b9052505b6001600160a01b03861615611111576001600160a01b0387168252604080516020601f87018190048102820181019092528581529086908690819084018382808284376000920191909152505050506101e0830152604051630eace54160e11b81526001600160a01b03871690631d59ca82906110de9085906004016139d5565b600060405180830381600087803b1580156110f857600080fd5b505af115801561110c573d6000803e3d6000fd5b505050505b61112382608001518360a001516127fe565b801561113f5761113b82608001518360a0015161236d565b600b555b604051806040016040528083606001516001600160a01b03168152602001836101400151815250925081602001516001600160a01b0316336001600160a01b03167fd175a80c109434bb89948928ab2475a6647c94244cb70002197896423c8833638461010001518561012001518660c001516040516111c1939291906137f8565b60405180910390a35050610a106001600855565b82804211156111f757604051630407b05b60e31b815260040160405180910390fd5b600061120588888888612ae0565b9050611248888286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b9992505050565b61126557604051638baa579f60e01b815260040160405180910390fd5b611270888888612846565b5050505050505050565b600060065446146112925761128d612cc5565b905090565b5060075490565b60408051600280825260608083018452926020830190803683370190505090507f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c6816000815181106112ed576112ed6139e6565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f81600181518110611341576113416139e6565b60200260200101906001600160a01b031690816001600160a01b03168152505090565b60408051808201909152600080825260208201526113806121d1565b61141e604051806101c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b61142a87890189613862565b60ff166101808401526001600160a01b039081166020840152166040820152600954600a5460a08301526080820152611461612203565b60e083015260c082015261147486612458565b95507f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c66001600160a01b031681604001516001600160a01b0316036115fc576114fe867f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c67f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f612516565b62ffffff166101608201526001600160a01b037f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f166060820152608081015160c082015161154c9190613628565b8161010001818152505061157b81610160015162ffffff1682610100015183608001518460a00151600161290d565b610140830152610120820181905260e08201805161159a908390613628565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822926115ef926000918291613a14565b60405180910390a3611785565b7f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f6001600160a01b031681604001516001600160a01b03161461163e57600080fd5b611689867f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f7f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c6612516565b62ffffff166101608201526001600160a01b037f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c616606082015260a081015160e08201516116d79190613628565b8161010001818152505061170681610160015162ffffff1682610100015183608001518460a00151600061290d565b610140830152610120820181905260c082018051611725908390613628565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229261177c9260009291908390613a49565b60405180910390a35b60c08101516001600160801b0310156117b157604051631a93c68960e11b815260040160405180910390fd5b60e08101516001600160801b0310156117dd57604051631a93c68960e11b815260040160405180910390fd5b6117fb816060015182602001518361012001518461018001516129c8565b6001600160a01b038516156118af576001600160a01b0386168152604080516020601f86018190048102820181019092528481529085908590819084018382808284376000920191909152505050506101a082015260405163608dbcbb60e01b81526001600160a01b0386169063608dbcbb9061187c908490600401613b9b565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050505b6118c18160c001518260e001516127fe565b60608101516001600160a01b0316825261012001516020820152610a106001600855565b604051634625a94d60e01b81526000906001600160a01b037f000000000000000000000000608cb7c3168427091f5994a45baf12083964b4a31690634625a94d9061193c9030908990899089908990600401613bac565b602060405180830381865afa158015611959573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197d9190613c09565b95945050505050565b60058054610a2790613836565b600954600a54600091907f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c66001600160a01b039081169087161483816119f9577f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c6611a1b565b7f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f5b9050611a39611a2b87838b612516565b62ffffff1688868686612d4e565b98975050505050505050565b6040516302a64b8360e21b81526000906001600160a01b037f000000000000000000000000608cb7c3168427091f5994a45baf12083964b4a31690630a992e0c90611a94903090600401613127565b602060405180830381865afa158015611ab1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128d9190613c09565b33600090815260016020526040812080548391908390611af6908490613628565b90915550506001600160a01b0383166000818152600160205260409081902080548501905551339060008051602061412c83398151915290611b39908690613038565b60405180910390a350600192915050565b8380421115611b6c57604051630407b05b60e31b815260040160405180910390fd5b6000611b7a89898989612ae0565b9050600060018287878760405160008152602001604052604051611ba19493929190613c2a565b6020604051602081039080840390855afa158015611bc3573d6000803e3d6000fd5b505050602060405103519050896001600160a01b0316816001600160a01b031614611c0157604051638baa579f60e01b815260040160405180910390fd5b6001600160a01b038116611c2857604051638baa579f60e01b815260040160405180910390fd5b611c338a8a8a612846565b50505050505050505050565b6060611c496121d1565b611cb460405180610140016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600060ff168152602001606081525090565b611cc087890189613c52565b60ff166101008301526001600160a01b03166020820152611cdf612203565b606083019081526040808401928352306000908152600160205290812054608085015291519051611d119190836125c8565b60a08401819052909150600003611d2757600080fd5b611d4882604001518360800151611d3e919061363f565b8360a00151900490565b60c083015260608201516080830151611d6491611d3e9161363f565b60e08301526080820151611d799030906128ae565b611db27f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c683602001518460c001518561010001516129c8565b611deb7f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f83602001518460e001518561010001516129c8565b60c082015160408301805191909103905260e08201516060830180519190910390526001600160a01b03861615611ec957611e2587612458565b6001600160a01b03168252604080516020601f870181900481028201810190925285815290869086908190840183828082843760009201919091525050505061012083015260405163109ea27d60e31b81526001600160a01b038716906384f513e890611e96908590600401613d4e565b600060405180830381600087803b158015611eb057600080fd5b505af1158015611ec4573d6000803e3d6000fd5b505050505b611edb826040015183606001516127fe565b8015611ef757611ef38260400151836060015161236d565b600b555b6040805160028082526060820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081611f0d57905050925060405180604001604052807f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c66001600160a01b031681526020018360c0015181525083600081518110611f8b57611f8b6139e6565b602002602001018190525060405180604001604052807f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f6001600160a01b031681526020018360e0015181525083600181518110611feb57611feb6139e6565b602002602001018190525081602001516001600160a01b0316336001600160a01b03167fd175a80c109434bb89948928ab2475a6647c94244cb70002197896423c8833638460c001518560e0015186608001516040516111c1939291906137f8565b600954600a54600091907f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c66001600160a01b039081169087161483816120b3577f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c66120d5565b7f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f5b90506120f36120e5878a84612516565b62ffffff168886868661290d565b5098975050505050505050565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b1790529051600091606091839182916001600160a01b0387169161214891613d81565b600060405180830381855afa9150503d8060008114612183576040519150601f19603f3d011682016040523d82523d6000602084013e612188565b606091505b509150915081156121b4576001818060200190518101906121a99190613de5565b935093505050915091565b600060405180602001604052806000815250935093505050915091565b6002600854036121fc5760405162461bcd60e51b81526004016121f390613e20565b60405180910390fd5b6002600855565b6000807f0000000000000000000000007160570bb153edd0ea1775ec2b2ac9b65f1ab61b6001600160a01b031663f7888aec7f0000000000000000000000001cc8c191f3362fc13b5ddf95e5fafb27e1b145c6306040518363ffffffff1660e01b8152600401612274929190613e5b565b602060405180830381865afa158015612291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b59190613e81565b604051633de222bb60e21b81529092506001600160a01b037f0000000000000000000000007160570bb153edd0ea1775ec2b2ac9b65f1ab61b169063f7888aec90612326907f000000000000000000000000e5d7c2a44ffddf6b295a15c148167daaaf5cf34f903090600401613e5b565b602060405180830381865afa158015612343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123679190613e81565b90509091565b60006001600160801b0383111561239757604051631a93c68960e11b815260040160405180910390fd5b6001600160801b038211156123bf57604051631a93c68960e11b815260040160405180910390fd5b610b976123cc838561363f565b70ffffffffffffffffffffffffffffffffff811160071b81811c68ffffffffffffffffff1060061b1781811c64ffffffffff1060051b1781811c62ffffff1060041b1781811c620100000160b5600192831c1b0260121c80830401811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b60006001600160a01b03821615612512576001600160a01b038216331461251257604051632af3bd5560e21b81526001600160a01b037f000000000000000000000000608cb7c3168427091f5994a45baf12083964b4a3169063abcef554906124c5903390600401613127565b602060405180830381865afa1580156124e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125069190613eb5565b61251257506000919050565b5090565b6000612533848484604051806020016040528060008152506118e5565b949350505050565b60008083600003612551575060009050806125bd565b848610612589576125826125658688613628565b61256f908a61363f565b61257d620186a0600261363f565b900490565b90506125bd565b600083612596868961363f565b6125a0919061368c565b90506125b96125af828a613628565b61256f908b61363f565b9250505b965096945050505050565b600080600054905060007f000000000000000000000000608cb7c3168427091f5994a45baf12083964b4a36001600160a01b0316634ccb20c06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612630573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126549190613ee1565b600b546001600160a01b038216151594509091508015612797578315612791578460000361268957612686878761236d565b94505b8085111561278c57600061269b611a45565b62ffffff1690506000816126af8489613628565b6126b9908761363f565b6126c3919061363f565b905060006126d1848461363f565b886126df85620186a0613628565b6126e9919061363f565b6126f3919061365e565b90506000612701828461368c565b905080156127875761271386826127a1565b604051631087d04360e31b81526001600160a01b0387169063843e82189061274690600190309086908a90600401613f17565b600060405180830381600087803b15801561276057600080fd5b505af1158015612774573d6000803e3d6000fd5b505050508087612784919061365e565b96505b505050505b612797565b6000600b555b5050935093915050565b806000808282546127b2919061365e565b90915550506001600160a01b0382166000818152600160205260408082208054850190555160008051602061412c833981519152906127f2908590613038565b60405180910390a35050565b600a81905560098290556040517fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a9061283a90849084906130b5565b60405180910390a15050565b6001600160a01b0380841660008181526002602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906128a1908590613038565b60405180910390a3505050565b6001600160a01b038216600090815260016020526040812080548392906128d6908490613628565b90915550506000805482900381556040516001600160a01b0384169060008051602061412c833981519152906127f2908590613038565b6000808560000361292157600091506129be565b600061293088620186a0613628565b61293a908861363f565b9050612952612949898961363f565b620186a0900490565b9150831561298d5780612968620186a08861363f565b612972919061365e565b61297c868361363f565b612986919061368c565b92506129bc565b8061299b620186a08761363f565b6129a5919061365e565b6129af878361363f565b6129b9919061368c565b92505b505b9550959350505050565b8060ff16600003612a5a576040516317d5759960e31b81526001600160a01b037f0000000000000000000000007160570bb153edd0ea1775ec2b2ac9b65f1ab61b169063beabacc890612a2390879087908790600401613f61565b600060405180830381600087803b158015612a3d57600080fd5b505af1158015612a51573d6000803e3d6000fd5b50505050612ada565b604051636cb568c160e01b81526001600160a01b037f0000000000000000000000007160570bb153edd0ea1775ec2b2ac9b65f1ab61b1690636cb568c190612aac908790879087908790600401613f7c565b600060405180830381600087803b158015612ac657600080fd5b505af1158015611270573d6000803e3d6000fd5b50505050565b6000612aea61127a565b6001600160a01b038616600090815260036020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c992899289928992909190612b3883613fb1565b9190505587604051602001612b5296959493929190613fcb565b60405160208183030381529060405280519060200120604051602001612b7992919061401a565b604051602081830303815290604052805190602001209050949350505050565b600080612ba68484612e09565b9050846001600160a01b0316816001600160a01b031603612bda576001600160a01b03811615612bda576001915050610b97565b600080866001600160a01b0316631626ba7e60e01b8787604051602401612c0292919061404b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612c409190613d81565b600060405180830381855afa9150503d8060008114612c7b576040519150601f19603f3d011682016040523d82523d6000602084013e612c80565b606091505b5091509150818015612c93575080516020145b8015612cba57508051630b135d3f60e11b90612cb89083016020908101908401613e81565b145b979650505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6004604051612cf791906140dd565b604051908190038120612d3392917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc690469030906020016140e9565b60405160208183030381529060405280519060200120905090565b600084600003612d605750600061197d565b8115612dbb57612d7386620186a0613628565b612d7d8686613628565b612d87919061363f565b620186a0612d95878661363f565b612d9f919061363f565b612da9919061368c565b612db490600161365e565b905061197d565b612dc886620186a0613628565b612dd28685613628565b612ddc919061363f565b620186a0612dea878761363f565b612df4919061363f565b612dfe919061368c565b610a1090600161365e565b60008151604114612e1c5750600061055b565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612e62576000935050505061055b565b60018682858560405160008152602001604052604051612e859493929190613c2a565b6020604051602081039080840390855afa158015612ea7573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b6001600160e01b031981165b8114612ed357600080fd5b50565b803561055b81612ebc565b600060208284031215612ef657612ef6600080fd5b60006125338484612ed6565b8015155b82525050565b6020810161055b8284612f02565b60008083601f840112612f2f57612f2f600080fd5b50813567ffffffffffffffff811115612f4a57612f4a600080fd5b602083019150836001820283011115612f6557612f65600080fd5b9250929050565b60006001600160a01b03821661055b565b612ec881612f6c565b803561055b81612f7d565b60008060008060008060808789031215612fad57612fad600080fd5b863567ffffffffffffffff811115612fc757612fc7600080fd5b612fd389828a01612f1a565b96509650506020612fe689828a01612f86565b9450506040612ff789828a01612f86565b935050606087013567ffffffffffffffff81111561301757613017600080fd5b61302389828a01612f1a565b92509250509295509295509295565b80612f06565b6020810161055b8284613032565b60005b83811015613061578181015183820152602001613049565b83811115612ada5750506000910152565b600061307c825190565b808452602084019350613093818560208601613046565b601f01601f19169290920192915050565b60208082528101610b978184613072565b604081016130c38285613032565b610b976020830184613032565b80612ec8565b803561055b816130d0565b600080604083850312156130f7576130f7600080fd5b60006131038585612f86565b9250506020613114858286016130d6565b9150509250929050565b612f0681612f6c565b6020810161055b828461311e565b60008060006060848603121561314d5761314d600080fd5b60006131598686612f86565b935050602061316a86828701612f86565b925050604061317b868287016130d6565b9150509250925092565b80516040830190613196848261311e565b506020820151612ada6020850182613032565b6040810161055b8284613185565b60008060008060008060a087890312156131d3576131d3600080fd5b60006131df8989612f86565b96505060206131f089828a01612f86565b955050604061320189828a016130d6565b945050606061321289828a016130d6565b935050608087013567ffffffffffffffff81111561301757613017600080fd5b60ff8116612f06565b6020810161055b8284613232565b6000613255838361311e565b505060200190565b6000613267825190565b80845260209384019383018060005b8381101561329b57815161328a8882613249565b975060208301925050600101613276565b509495945050505050565b60208082528101610b97818461325d565b6000602082840312156132cc576132cc600080fd5b60006125338484612f86565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff82111715613314576133146132d8565b6040525050565b600061332660405190565b905061333282826132ee565b919050565b600067ffffffffffffffff821115613351576133516132d8565b601f19601f83011660200192915050565b82818337506000910152565b600061338161337c84613337565b61331b565b90508281526020810184848401111561339c5761339c600080fd5b6133a7848285613362565b509392505050565b600082601f8301126133c3576133c3600080fd5b813561253384826020860161336e565b600080600080608085870312156133ec576133ec600080fd5b60006133f88787612f86565b945050602061340987828801612f86565b935050604061341a87828801612f86565b925050606085013567ffffffffffffffff81111561343a5761343a600080fd5b613446878288016133af565b91505092959194509250565b62ffffff8116612f06565b6020810161055b8284613452565b60008060006060848603121561348357613483600080fd5b600061348f8686612f86565b93505060206134a0868287016130d6565b925050604061317b86828701612f86565b61ffff8116612f06565b6020810161055b82846134b1565b60ff8116612ec8565b803561055b816134c9565b600080600080600080600060e0888a0312156134fb576134fb600080fd5b60006135078a8a612f86565b97505060206135188a828b01612f86565b96505060406135298a828b016130d6565b955050606061353a8a828b016130d6565b945050608061354b8a828b016134d2565b93505060a061355c8a828b016130d6565b92505060c061356d8a828b016130d6565b91505092959891949750929550565b6000806040838503121561359257613592600080fd5b600061359e8585612f86565b925050602061311485828601612f86565b60006135bb8383613185565b505060400190565b60006135cd825190565b80845260209384019383018060005b8381101561329b5781516135f088826135af565b9750602083019250506001016135dc565b60208082528101610b9781846135c3565b634e487b7160e01b600052601160045260246000fd5b60008282101561363a5761363a613612565b500390565b600081600019048311821515161561365957613659613612565b500290565b6000821982111561367157613671613612565b500190565b634e487b7160e01b600052601260045260246000fd5b60008261369b5761369b613676565b500490565b80516000906102008401906136b5858261311e565b5060208301516136c8602086018261311e565b5060408301516136db6040860182613032565b5060608301516136ee6060860182613032565b5060808301516137016080860182613032565b5060a083015161371460a0860182613032565b5060c083015161372760c0860182613032565b5060e083015161373a60e0860182613032565b5061010083015161374f610100860182613032565b50610120830151613764610120860182613032565b50610140830151613779610140860182613032565b5061016083015161378e610160860182613032565b506101808301516137a3610180860182613032565b506101a08301516137b86101a0860182613032565b506101c08301516137cd6101c0860182613452565b506101e08301518482036101e086015261197d8282613072565b60208082528101610b9781846136a0565b606081016138068286613032565b6138136020830185613032565b6125336040830184613032565b634e487b7160e01b600052602260045260246000fd5b60028104600182168061384a57607f821691505b60208210810361385c5761385c613820565b50919050565b60008060006060848603121561387a5761387a600080fd5b60006138868686612f86565b935050602061389786828701612f86565b925050604061317b868287016134d2565b80516000906102008401906138bd858261311e565b5060208301516138d0602086018261311e565b5060408301516138e3604086018261311e565b5060608301516138f6606086018261311e565b5060808301516139096080860182613032565b5060a083015161391c60a0860182613032565b5060c083015161392f60c0860182613032565b5060e083015161394260e0860182613032565b50610100830151613957610100860182613032565b5061012083015161396c610120860182613032565b50610140830151613981610140860182613032565b50610160830151613996610160860182613032565b506101808301516139ab610180860182613032565b506101a08301516139c06101a0860182613452565b506101c08301516137cd6101c0860182613232565b60208082528101610b9781846138a8565b634e487b7160e01b600052603260045260246000fd5b600061055b613a088381565b90565b612f06816139fc565b60808101613a228287613032565b613a2f6020830186613a0b565b613a3c6040830185613a0b565b61197d6060830184613032565b60808101613a578287613a0b565b613a646020830186613032565b613a716040830185613032565b61197d6060830184613a0b565b80516000906101c0840190613a93858261311e565b506020830151613aa6602086018261311e565b506040830151613ab9604086018261311e565b506060830151613acc606086018261311e565b506080830151613adf6080860182613032565b5060a0830151613af260a0860182613032565b5060c0830151613b0560c0860182613032565b5060e0830151613b1860e0860182613032565b50610100830151613b2d610100860182613032565b50610120830151613b42610120860182613032565b50610140830151613b57610140860182613032565b50610160830151613b6c610160860182613452565b50610180830151613b81610180860182613232565b506101a08301518482036101a086015261197d8282613072565b60208082528101610b978184613a7e565b60a08101613bba828861311e565b613bc7602083018761311e565b613bd4604083018661311e565b613be1606083018561311e565b8181036080830152612cba8184613072565b62ffffff8116612ec8565b805161055b81613bf3565b600060208284031215613c1e57613c1e600080fd5b60006125338484613bfe565b60808101613c388287613032565b613c456020830186613232565b613a3c6040830185613032565b60008060408385031215613c6857613c68600080fd5b6000613c748585612f86565b9250506020613114858286016134d2565b8051600090610140840190613c9a858261311e565b506020830151613cad602086018261311e565b506040830151613cc06040860182613032565b506060830151613cd36060860182613032565b506080830151613ce66080860182613032565b5060a0830151613cf960a0860182613032565b5060c0830151613d0c60c0860182613032565b5060e0830151613d1f60e0860182613032565b50610100830151613d34610100860182613232565b5061012083015184820361012086015261197d8282613072565b60208082528101610b978184613c85565b6000613d69825190565b613d77818560208601613046565b9290920192915050565b6000610b978284613d5f565b6000613d9b61337c84613337565b905082815260208101848484011115613db657613db6600080fd5b6133a7848285613046565b600082601f830112613dd557613dd5600080fd5b8151612533848260208601613d8d565b600060208284031215613dfa57613dfa600080fd5b815167ffffffffffffffff811115613e1457613e14600080fd5b61253384828501613dc1565b6020808252810161055b81601f81527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00602082015260400190565b60408101613e69828561311e565b610b97602083018461311e565b805161055b816130d0565b600060208284031215613e9657613e96600080fd5b60006125338484613e76565b801515612ec8565b805161055b81613ea2565b600060208284031215613eca57613eca600080fd5b60006125338484613eaa565b805161055b81612f7d565b600060208284031215613ef657613ef6600080fd5b60006125338484613ed6565b600061ffff821661055b565b612f0681613f02565b60a08101613f258287613f0e565b613f32602083018661311e565b613f3f6040830185613032565b613f4c6060830184613032565b81810360808301526000815260208101610a10565b60608101613f6f828661311e565b613813602083018561311e565b60808101613f8a828761311e565b613f97602083018661311e565b613fa46040830185613032565b61197d6060830184613232565b60006000198203613fc457613fc4613612565b5060010190565b60c08101613fd98289613032565b613fe6602083018861311e565b613ff3604083018761311e565b6140006060830186613032565b61400d6080830185613032565b612cba60a0830184613032565b61190160f01b815260020160006140318285613032565b6020820191506140418284613032565b5060200192915050565b604081016140598285613032565b81810360208301526125338184613072565b6000815461407881613836565b60018216801561408f57600181146140a4576140d4565b60ff19831686528115158202860193506140d4565b60008581526020902060005b838110156140cc578154888201526001909101906020016140b0565b838801955050505b50505092915050565b6000610b97828461406b565b60a081016140f78288613a0b565b6141046020830187613032565b6141116040830186613a0b565b61411e6060830185613032565b610a10608083018461311e56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212209d4df6080488c965e85c8d46a748d3e9c678e134194f5c0fad6ef2903c78217b64736f6c634300080f0033
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.