Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 387 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Create Pool | 14163915 | 20 days ago | IN | 0 ETH | 0.00014264 | ||||
Create Pool | 13862050 | 27 days ago | IN | 0 ETH | 0.00015084 | ||||
Create Pool | 13559562 | 35 days ago | IN | 0 ETH | 0.00104057 | ||||
Create Pool | 13449111 | 37 days ago | IN | 0 ETH | 0.00014143 | ||||
Create Pool | 11877795 | 75 days ago | IN | 0 ETH | 0.00056158 | ||||
Create Pool | 10331941 | 111 days ago | IN | 0 ETH | 0.00020526 | ||||
Create Pool | 9928965 | 121 days ago | IN | 0 ETH | 0.00069699 | ||||
Create Pool | 9928900 | 121 days ago | IN | 0 ETH | 0.00069699 | ||||
Create Pool | 9928843 | 121 days ago | IN | 0 ETH | 0.00070122 | ||||
Create Pool | 9928718 | 121 days ago | IN | 0 ETH | 0.00079359 | ||||
Create Pool | 9928604 | 121 days ago | IN | 0 ETH | 0.00071438 | ||||
Create Pool | 9928587 | 121 days ago | IN | 0 ETH | 0.00072303 | ||||
Create Pool | 9927686 | 121 days ago | IN | 0 ETH | 0.00085323 | ||||
Create Pool | 9927545 | 121 days ago | IN | 0 ETH | 0.00086353 | ||||
Create Pool | 9927458 | 121 days ago | IN | 0 ETH | 0.00086353 | ||||
Create Pool | 9927321 | 121 days ago | IN | 0 ETH | 0.00084347 | ||||
Create Pool | 9927188 | 121 days ago | IN | 0 ETH | 0.00088332 | ||||
Create Pool | 9927085 | 121 days ago | IN | 0 ETH | 0.00079856 | ||||
Create Pool | 9927060 | 121 days ago | IN | 0 ETH | 0.00079758 | ||||
Create Pool | 9927038 | 121 days ago | IN | 0 ETH | 0.00079758 | ||||
Create Pool | 9926830 | 121 days ago | IN | 0 ETH | 0.00078647 | ||||
Create Pool | 9926817 | 121 days ago | IN | 0 ETH | 0.00079117 | ||||
Create Pool | 9926784 | 121 days ago | IN | 0 ETH | 0.00078647 | ||||
Create Pool | 9926751 | 121 days ago | IN | 0 ETH | 0.00078263 | ||||
Create Pool | 9926737 | 121 days ago | IN | 0 ETH | 0.00078235 |
Latest 25 internal transactions (View All)
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
14990611 | 2 hrs ago | 0 ETH | ||||
14987790 | 4 hrs ago | 0 ETH | ||||
14985922 | 5 hrs ago | 0 ETH | ||||
14985922 | 5 hrs ago | 0 ETH | ||||
14985922 | 5 hrs ago | 0 ETH | ||||
14979801 | 8 hrs ago | 0 ETH | ||||
14979801 | 8 hrs ago | 0 ETH | ||||
14979801 | 8 hrs ago | 0 ETH | ||||
14979801 | 8 hrs ago | 0 ETH | ||||
14979801 | 8 hrs ago | 0 ETH | ||||
14968717 | 15 hrs ago | 0 ETH | ||||
14968717 | 15 hrs ago | 0 ETH | ||||
14968717 | 15 hrs ago | 0 ETH | ||||
14968717 | 15 hrs ago | 0 ETH | ||||
14968717 | 15 hrs ago | 0 ETH | ||||
14961253 | 19 hrs ago | 0 ETH | ||||
14961253 | 19 hrs ago | 0 ETH | ||||
14961253 | 19 hrs ago | 0 ETH | ||||
14959274 | 21 hrs ago | 0 ETH | ||||
14945201 | 29 hrs ago | 0 ETH | ||||
14945201 | 29 hrs ago | 0 ETH | ||||
14945201 | 29 hrs ago | 0 ETH | ||||
14938250 | 33 hrs ago | 0 ETH | ||||
14938250 | 33 hrs ago | 0 ETH | ||||
14938250 | 33 hrs ago | 0 ETH |
Loading...
Loading
Contract Name:
SyncSwapClassicPoolFactory
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 "../../interfaces/master/IPoolMaster.sol"; import "../../interfaces/token/IERC20.sol"; import "../BasePoolFactory.sol"; import "./SyncSwapClassicPool.sol"; contract SyncSwapClassicPoolFactory is BasePoolFactory { constructor(address _master) BasePoolFactory(_master) { } function _createPool(address token0, address token1) internal override returns (address pool) { // Perform sanity checks. IERC20(token0).balanceOf(address(this)); IERC20(token1).balanceOf(address(this)); bytes memory deployData = abi.encode(token0, token1); cachedDeployData = deployData; // The salt is same with deployment data. bytes32 salt = keccak256(deployData); pool = address(new SyncSwapClassicPool{salt: salt}()); // this will prevent duplicated pools. // Register the pool. The config is same with deployment data. IPoolMaster(master).registerPool(pool, 1, deployData); } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity >=0.5.0; import "./IPoolFactory.sol"; interface IBasePoolFactory is IPoolFactory { event PoolCreated( address indexed token0, address indexed token1, address pool ); function getPool(address tokenA, address tokenB) external view returns (address pool); function getSwapFee( address pool, address sender, address tokenIn, address tokenOut, bytes calldata data ) external view returns (uint24 swapFee); }
// 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 { function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } function geometricMean(uint a, uint b) internal pure returns (uint) { return Math.sqrt(a * b); } /// @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) ); } }
// SPDX-License-Identifier: AGPL-3.0-or-later pragma solidity ^0.8.0; import "../interfaces/factory/IBasePoolFactory.sol"; import "../interfaces/master/IPoolMaster.sol"; error InvalidTokens(); abstract contract BasePoolFactory is IBasePoolFactory { /// @dev The pool master that control fees and registry. address public immutable master; /// @dev Pools by its two pool tokens. mapping(address => mapping(address => address)) public override getPool; bytes internal cachedDeployData; constructor(address _master) { master = _master; } function getDeployData() external view override returns (bytes memory deployData) { deployData = cachedDeployData; } function getSwapFee( address pool, address sender, address tokenIn, address tokenOut, bytes calldata data ) external view override returns (uint24 swapFee) { swapFee = IPoolMaster(master).getSwapFee(pool, sender, tokenIn, tokenOut, data); } function createPool(bytes calldata data) external override returns (address pool) { (address tokenA, address tokenB) = abi.decode(data, (address, address)); // Perform safety checks. if (tokenA == tokenB) { revert InvalidTokens(); } // Sort tokens. if (tokenB < tokenA) { (tokenA, tokenB) = (tokenB, tokenA); } if (tokenA == address(0)) { revert InvalidTokens(); } // Underlying implementation to deploy the pools and register them. pool = _createPool(tokenA, tokenB); // Populate mapping in both directions. // Not necessary as existence of the master, but keep them for better compatibility. getPool[tokenA][tokenB] = pool; getPool[tokenB][tokenA] = pool; emit PoolCreated(tokenA, tokenB, pool); } function _createPool(address tokenA, address tokenB) internal virtual returns (address) { } }
// 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(); } }
{ "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":[{"internalType":"address","name":"_master","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidTokens","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"pool","type":"address"}],"name":"PoolCreated","type":"event"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"createPool","outputs":[{"internalType":"address","name":"pool","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getDeployData","outputs":[{"internalType":"bytes","name":"deployData","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getPool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pool","type":"address"},{"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":"master","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60a060405234801561001057600080fd5b5060405161599a38038061599a83398101604081905261002f91610075565b6001600160a01b031660805261009e565b60006001600160a01b0382165b92915050565b61005c81610040565b811461006757600080fd5b50565b805161004d81610053565b60006020828403121561008a5761008a600080fd5b6000610096848461006a565b949350505050565b6080516158d36100c76000396000818161010b0152818161027e015261051c01526158d36000f3fe60806040523480156200001157600080fd5b50600436106200005e5760003560e01c806313b8683f14620000635780634625a94d1462000092578063531aa03e14620000b8578063d039f62214620000ec578063ee97f7f31462000105575b600080fd5b6200007a62000074366004620005fa565b6200012d565b6040516200008991906200066c565b60405180910390f35b620000a9620000a3366004620006a3565b62000264565b60405162000089919062000753565b6200007a620000c936600462000763565b60006020818152928152604080822090935290815220546001600160a01b031681565b620000f66200030e565b60405162000089919062000810565b6200007a7f000000000000000000000000000000000000000000000000000000000000000081565b600080806200013f8486018662000763565b91509150806001600160a01b0316826001600160a01b03160362000176576040516333910aef60e11b815260040160405180910390fd5b816001600160a01b0316816001600160a01b031610156200019357905b6001600160a01b038216620001bb576040516333910aef60e11b815260040160405180910390fd5b620001c78282620003a8565b6001600160a01b0380841660008181526020818152604080832087861680855290835281842080549688166001600160a01b03199788168117909155848452828520868652909352928190208054909516909117909355915192955090917f9c5d829b9b23efc461f9aeef91979ec04bb903feb3bee4f26d22114abfc7335b90620002549087906200066c565b60405180910390a3505092915050565b604051634625a94d60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690634625a94d90620002bf908a908a908a908a908a908a906004016200085c565b602060405180830381865afa158015620002dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003039190620008d3565b979650505050505050565b6060600180546200031f9062000916565b80601f01602080910402602001604051908101604052809291908181526020018280546200034d9062000916565b80156200039e5780601f1062000372576101008083540402835291602001916200039e565b820191906000526020600020905b8154815290600101906020018083116200038057829003601f168201915b5050505050905090565b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190620003d99030906004016200066c565b602060405180830381865afa158015620003f7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041d91906200095a565b506040516370a0823160e01b81526001600160a01b038316906370a08231906200044c9030906004016200066c565b602060405180830381865afa1580156200046a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200049091906200095a565b5060008383604051602001620004a89291906200097f565b60408051601f1981840301815291905290506001620004c8828262000a6b565b50805160208201206040518190620004e09062000594565b8190604051809103906000f590508015801562000501573d6000803e3d6000fd5b5060405163784198d960e01b81529093506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063784198d99062000558908690600190879060040162000b54565b600060405180830381600087803b1580156200057357600080fd5b505af115801562000588573d6000803e3d6000fd5b50505050505092915050565b614d0d8062000b9183390190565b60008083601f840112620005b957620005b9600080fd5b50813567ffffffffffffffff811115620005d657620005d6600080fd5b602083019150836001820283011115620005f357620005f3600080fd5b9250929050565b60008060208385031215620006125762000612600080fd5b823567ffffffffffffffff8111156200062e576200062e600080fd5b6200063c85828601620005a2565b92509250509250929050565b60006001600160a01b0382165b92915050565b620006668162000648565b82525050565b602081016200065582846200065b565b620006878162000648565b81146200069357600080fd5b50565b803562000655816200067c565b60008060008060008060a08789031215620006c157620006c1600080fd5b6000620006cf898962000696565b9650506020620006e289828a0162000696565b9550506040620006f589828a0162000696565b94505060606200070889828a0162000696565b935050608087013567ffffffffffffffff8111156200072a576200072a600080fd5b6200073889828a01620005a2565b92509250509295509295509295565b62ffffff811662000666565b6020810162000655828462000747565b600080604083850312156200077b576200077b600080fd5b600062000789858562000696565b92505060206200079c8582860162000696565b9150509250929050565b60005b83811015620007c3578181015183820152602001620007a9565b83811115620007d3576000848401525b50505050565b6000620007e4825190565b808452602084019350620007fd818560208601620007a6565b601f19601f8201165b9093019392505050565b60208082528101620008238184620007d9565b9392505050565b82818337506000910152565b81835260006020840193506200084e8385846200082a565b601f19601f84011662000806565b60a081016200086c82896200065b565b6200087b60208301886200065b565b6200088a60408301876200065b565b6200089960608301866200065b565b8181036080830152620008ae81848662000836565b98975050505050505050565b62ffffff811662000687565b80516200065581620008ba565b600060208284031215620008ea57620008ea600080fd5b6000620008f88484620008c6565b949350505050565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806200092b57607f821691505b60208210810362000940576200094062000900565b50919050565b8062000687565b8051620006558162000946565b600060208284031215620009715762000971600080fd5b6000620008f884846200094d565b604081016200098f82856200065b565b6200082360208301846200065b565b634e487b7160e01b600052604160045260246000fd5b600062000655620009c28381565b90565b620009d083620009b4565b81546008840282811b60001990911b908116901990911617825550505050565b6000620009ff818484620009c5565b505050565b8181101562000a235762000a1a600082620009f0565b60010162000a04565b5050565b601f821115620009ff576000818152602090206020601f8501048101602085101562000a505750805b62000a646020601f86010483018262000a04565b5050505050565b815167ffffffffffffffff81111562000a885762000a886200099e565b62000a94825462000916565b62000aa182828562000a27565b6020601f83116001811462000ad8576000841562000abf5750858201515b600019600886021c198116600286021786555062000b34565b600085815260208120601f198616915b8281101562000b0a578885015182556020948501946001909201910162000ae8565b8683101562000b275784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b600061ffff821662000655565b620006668162000b3c565b6060810162000b6482866200065b565b62000b73602083018562000b49565b818103604083015262000b878184620007d9565b9594505050505056fe61012060405260126080523480156200001757600080fd5b5060016008819055506000336001600160a01b031663d039f6226040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000061573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200008b919081019062000597565b905060008082806020019051810190620000a6919062000611565b915091506000336001600160a01b031663ee97f7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000111919062000654565b9050806001600160a01b031660a0816001600160a01b031681525050806001600160a01b031663fbfa77cf6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200016c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000192919062000654565b6001600160a01b0390811660c05282811661010052831660e052600080620001c685620002c2602090811b6200210017901c565b91509150600080620001e386620002c260201b620021001760201c565b91509150838015620001f25750815b1562000251576200024b8382604051602001620002119291906200069e565b604051602081830303815290604052848360405160200162000235929190620006f3565b60408051601f198184030181529190526200039a565b620002b4565b620002b46040518060400160405280601381526020017f53796e635377617020436c6173736963204c500000000000000000000000000081525060405180604001604052806004815260200163063534c560e41b8152506200039a60201b60201c565b505050505050505062000a13565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b1790529051600091606091839182916001600160a01b038716916200030c9162000730565b600060405180830381855afa9150503d806000811462000349576040519150601f19603f3d011682016040523d82523d6000602084013e6200034e565b606091505b509150915081156200037d5760018180602001905181019062000372919062000597565b935093505050915091565b600060405180602001604052806000815250935093505050915091565b6004620003a8838262000842565b506005620003b7828262000842565b5046600655620003c6620003cd565b6007555050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60046040516200040191906200098c565b6040519081900381206200043f92917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69046903090602001620009bd565b60405160208183030381529060405280519060200120905090565b634e487b7160e01b600052604160045260246000fd5b601f19601f83011681018181106001600160401b03821117156200049857620004986200045a565b6040525050565b6000620004ab60405190565b9050620004b9828262000470565b919050565b60006001600160401b03821115620004da57620004da6200045a565b601f19601f83011660200192915050565b60005b8381101562000508578181015183820152602001620004ee565b8381111562000518576000848401525b50505050565b6000620005356200052f84620004be565b6200049f565b905082815260208101848484011115620005525762000552600080fd5b6200055f848285620004eb565b509392505050565b600082601f8301126200057d576200057d600080fd5b81516200058f8482602086016200051e565b949350505050565b600060208284031215620005ae57620005ae600080fd5b81516001600160401b03811115620005c957620005c9600080fd5b6200058f8482850162000567565b60006001600160a01b0382165b92915050565b620005f581620005d7565b81146200060157600080fd5b50565b8051620005e481620005ea565b60008060408385031215620006295762000629600080fd5b600062000637858562000604565b92505060206200064a8582860162000604565b9150509250929050565b6000602082840312156200066b576200066b600080fd5b60006200058f848462000604565b600062000684825190565b62000694818560208601620004eb565b9290920192915050565b68029bcb731a9bbb0b8160bd1b81526009016000620006be828562000679565b602f60f81b81526001019150620006d6828462000679565b6a020436c6173736963204c560ac1b81529150600b82016200058f565b600062000701828562000679565b602f60f81b8152600101915062000719828462000679565b6402063534c560dc1b81529150600582016200058f565b60006200073e828462000679565b9392505050565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806200077057607f821691505b60208210810362000785576200078562000745565b50919050565b6000620005e4620007998381565b90565b620007a7836200078b565b81546008840282811b60001990911b908116901990911617825550505050565b6000620007d68184846200079c565b505050565b81811015620007fa57620007f1600082620007c7565b600101620007db565b5050565b601f821115620007d6576000818152602090206020601f85010481016020851015620008275750805b6200083b6020601f860104830182620007db565b5050505050565b81516001600160401b038111156200085e576200085e6200045a565b6200086a82546200075b565b62000877828285620007fe565b6020601f831160018114620008ae5760008415620008955750858201515b600019600886021c19811660028602178655506200090a565b600085815260208120601f198616915b82811015620008e05788850151825560209485019460019092019101620008be565b86831015620008fd5784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b6000815462000921816200075b565b6001821680156200093b5760018114620009515762000983565b60ff198316865281151582028601935062000983565b60008581526020902060005b838110156200097b578154888201526001909101906020016200095d565b838801955050505b50505092915050565b60006200073e828462000912565b620009a5816200078b565b82525050565b80620009a5565b620009a581620005d7565b60a08101620009cd82886200099a565b620009dc6020830187620009ab565b620009eb60408301866200099a565b620009fa6060830185620009ab565b62000a096080830184620009b2565b9695505050505050565b60805160a05160c05160e0516101005161418162000b8c6000396000818161042e015281816106fd0152818161073701528181610d4201528181610da401528181610e6801528181610f1401528181610f700152818161130f015281816114da01528181611513015281816115fe01528181611644015281816119fb01528181611db701528181611fa3015281816120b501526122fc015260008181610288015281816106dc0152818161075801528181610d8301528181610ddf01528181610ece01528181610f3501528181610ffd015281816112bb01528181611478015281816114b9015281816116650152818161169e0152818161199f015281816119d501528181611d7e01528181611f43015281816120590152818161208f01526122370152600081816104da01528181612208015281816122cf015281816129ea0152612a71015260008181610493015281816118ff01528181611a5f0152818161249001526125d40152600061030d01526141816000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c806370a082311161010f578063b1dd61b6116100a2578063ee97f7f311610071578063ee97f7f31461048e578063f66eab5b146104b5578063fbfa77cf146104d5578063ff9c8ac6146104fc57600080fd5b8063b1dd61b614610414578063d21220a714610429578063d505accf14610450578063dd62ed3e1461046357600080fd5b806395d89b41116100de57806395d89b41146103de578063a287c795146103e6578063a5a41031146103f9578063a9059cbb1461040157600080fd5b806370a082311461036b5780637132bb7f1461038b5780637ecebe001461039e5780638b4c5470146103be57600080fd5b806323b872dd116101875780633644e515116101565780633644e5151461033c578063443cb4bc146103445780635a76f25e1461034d57806367e4ac2c1461035657600080fd5b806323b872dd146102c057806327b0bcea146102d35780632c0198cc146102f3578063313ce5671461030857600080fd5b80630902f1ac116101c35780630902f1ac1461025c578063095ea7b3146102705780630dfe16811461028357806318160ddd146102b757600080fd5b806301ffc9a7146101f557806303e7286a1461021e57806306fdde031461023e57806307f293f714610253575b600080fd5b610208610203366004612ee1565b61050f565b6040516102159190612f0c565b60405180910390f35b61023161022c366004612f91565b610561565b6040516102159190613038565b610246610a1a565b60405161021591906130a4565b610231600b5481565b600954600a546040516102159291906130b5565b61020861027e3660046130e1565b610aa8565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516102159190613127565b61023160005481565b6102086102ce366004613135565b610abe565b6102e66102e1366004612f91565b610b9e565b60405161021591906131a9565b6103066103013660046131b7565b6111d5565b005b61032f7f000000000000000000000000000000000000000000000000000000000000000081565b604051610215919061323b565b61023161127a565b61023160095481565b610231600a5481565b61035e611299565b60405161021591906132a6565b6102316103793660046132b7565b60016020526000908152604090205481565b6102e6610399366004612f91565b611364565b6102316103ac3660046132b7565b60036020526000908152604090205481565b6103d16103cc3660046133d3565b6118e5565b604051610215919061345d565b610246611986565b6102316103f436600461346b565b611993565b6103d1611a45565b61020861040f3660046130e1565b611ad5565b61041c600181565b60405161021591906134bb565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b61030661045e3660046134dd565b611b4a565b61023161047136600461357c565b600260209081526000928352604080842090915290825290205481565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b6104c86104c3366004612f91565b611c3f565b6040516102159190613601565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b61023161050a36600461346b565b61204d565b60006001600160e01b031982166301ffc9a760e01b148061054057506001600160e01b0319821663d505accf60e01b145b8061055b57506001600160e01b03198216630b00663360e21b145b92915050565b600061056b6121d1565b61060260405180610200016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001606081525090565b61060e878901896132b7565b6001600160a01b03166020820152600954600a5460608301526040820152610634612203565b60a083018190526080830182905261064c919061236d565b610140820152604081015160808201516106669190613628565b60c0820152606081015160a082015161067f9190613628565b60e082015261068d86612458565b9550600081604001516000146106c3576106be82606001518360c001516106b4919061363f565b8360400151900490565b6106c6565b60005b60e08301519091508111801561073157610721887f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101c0840152610788565b61077c887f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101c08401525b6107b0836101c0015162ffffff168460c001518560e00151858760400151886060015161253b565b61012085015261010084018190526040840180516107cf90839061365e565b9052506101208301516060840180516107e990839061365e565b90525060408301516060840151610800919061236d565b610160840181905260009061081890829081906125c8565b6101808601819052909150600003610855576103e884610140015161083d9190613628565b6101a085015261085060006103e86127a1565b61088d565b610160840151610180850151610140860151610872908390613628565b61087c919061363f565b610886919061368c565b6101a08501525b836101a001516000036108b357604051633489be7560e21b815260040160405180910390fd5b6108c68460200151856101a001516127a1565b6001600160a01b0388161561097a576001600160a01b0389168452604080516020601f89018190048102820181019092528781529088908890819084018382808284376000920191909152505050506101e0850152604051630204997360e41b81526001600160a01b038916906320499730906109479087906004016137e7565b600060405180830381600087803b15801561096157600080fd5b505af1158015610975573d6000803e3d6000fd5b505050505b61098c84608001518560a001516127fe565b801561099c57610140840151600b555b83602001516001600160a01b0316336001600160a01b03167fa8137fff86647d8a402117b9c5dbda627f721d3773338fb9678c83e54ed390808660c001518760e00151886101a001516040516109f4939291906137f8565b60405180910390a35050506101a001519050610a106001600855565b9695505050505050565b60048054610a2790613836565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5390613836565b8015610aa05780601f10610a7557610100808354040283529160200191610aa0565b820191906000526020600020905b815481529060010190602001808311610a8357829003601f168201915b505050505081565b6000610ab5338484612846565b50600192915050565b6001600160a01b03831660009081526002602090815260408083203384529091528120546000198114610b1a57610af58382613628565b6001600160a01b03861660009081526002602090815260408083203384529091529020555b6001600160a01b03851660009081526001602052604081208054859290610b42908490613628565b90915550506001600160a01b038085166000818152600160205260409081902080548701905551909187169060008051602061412c83398151915290610b89908790613038565b60405180910390a360019150505b9392505050565b6040805180820190915260008082526020820152610bba6121d1565b610c6660405180610200016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b610c7287890189613862565b60ff166101c08401526001600160a01b039081166020840152166060820152610c99612203565b60a08301908152608083019182523060009081526001602052604081205460c085015291519051610ccb9190836125c8565b60e08401819052909150600003610ce157600080fd5b610d0282608001518360c00151610cf8919061363f565b8360e00151900490565b61010083015260a082015160c0830151610d1f91610cf89161363f565b61012083015260c0820151610d359030906128ae565b610d3e87612458565b96507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682606001516001600160a01b031603610ecc57610dc8877f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101a083018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408401526101008301516080840151610e3c929190610e20908290613628565b8561012001518660a00151610e359190613628565b600161290d565b610180840152610160830181905261012083018051610e5c90839061365e565b91508181525050610e9d7f00000000000000000000000000000000000000000000000000000000000000008360200151846101200151856101c001516129c8565b6101208201516101408301819052600061010084015260a083018051610ec4908390613628565b90525061105d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682606001516001600160a01b031614610f0e57600080fd5b610f59877f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101a083018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408401526101208301516101008401516080850151610fd1939291610fb591613628565b8561012001518660a00151610fca9190613628565b600061290d565b610180840152610160830181905261010083018051610ff190839061365e565b915081815250506110327f00000000000000000000000000000000000000000000000000000000000000008360200151846101000151856101c001516129c8565b61010082015161014083018190526000610120840152608083018051611059908390613628565b9052505b6001600160a01b03861615611111576001600160a01b0387168252604080516020601f87018190048102820181019092528581529086908690819084018382808284376000920191909152505050506101e0830152604051630eace54160e11b81526001600160a01b03871690631d59ca82906110de9085906004016139d5565b600060405180830381600087803b1580156110f857600080fd5b505af115801561110c573d6000803e3d6000fd5b505050505b61112382608001518360a001516127fe565b801561113f5761113b82608001518360a0015161236d565b600b555b604051806040016040528083606001516001600160a01b03168152602001836101400151815250925081602001516001600160a01b0316336001600160a01b03167fd175a80c109434bb89948928ab2475a6647c94244cb70002197896423c8833638461010001518561012001518660c001516040516111c1939291906137f8565b60405180910390a35050610a106001600855565b82804211156111f757604051630407b05b60e31b815260040160405180910390fd5b600061120588888888612ae0565b9050611248888286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b9992505050565b61126557604051638baa579f60e01b815260040160405180910390fd5b611270888888612846565b5050505050505050565b600060065446146112925761128d612cc5565b905090565b5060075490565b60408051600280825260608083018452926020830190803683370190505090507f0000000000000000000000000000000000000000000000000000000000000000816000815181106112ed576112ed6139e6565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600181518110611341576113416139e6565b60200260200101906001600160a01b031690816001600160a01b03168152505090565b60408051808201909152600080825260208201526113806121d1565b61141e604051806101c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b61142a87890189613862565b60ff166101808401526001600160a01b039081166020840152166040820152600954600a5460a08301526080820152611461612203565b60e083015260c082015261147486612458565b95507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681604001516001600160a01b0316036115fc576114fe867f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101608201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166060820152608081015160c082015161154c9190613628565b8161010001818152505061157b81610160015162ffffff1682610100015183608001518460a00151600161290d565b610140830152610120820181905260e08201805161159a908390613628565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822926115ef926000918291613a14565b60405180910390a3611785565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681604001516001600160a01b03161461163e57600080fd5b611689867f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101608201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016606082015260a081015160e08201516116d79190613628565b8161010001818152505061170681610160015162ffffff1682610100015183608001518460a00151600061290d565b610140830152610120820181905260c082018051611725908390613628565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229261177c9260009291908390613a49565b60405180910390a35b60c08101516001600160801b0310156117b157604051631a93c68960e11b815260040160405180910390fd5b60e08101516001600160801b0310156117dd57604051631a93c68960e11b815260040160405180910390fd5b6117fb816060015182602001518361012001518461018001516129c8565b6001600160a01b038516156118af576001600160a01b0386168152604080516020601f86018190048102820181019092528481529085908590819084018382808284376000920191909152505050506101a082015260405163608dbcbb60e01b81526001600160a01b0386169063608dbcbb9061187c908490600401613b9b565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050505b6118c18160c001518260e001516127fe565b60608101516001600160a01b0316825261012001516020820152610a106001600855565b604051634625a94d60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690634625a94d9061193c9030908990899089908990600401613bac565b602060405180830381865afa158015611959573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197d9190613c09565b95945050505050565b60058054610a2790613836565b600954600a54600091907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b039081169087161483816119f9577f0000000000000000000000000000000000000000000000000000000000000000611a1b565b7f00000000000000000000000000000000000000000000000000000000000000005b9050611a39611a2b87838b612516565b62ffffff1688868686612d4e565b98975050505050505050565b6040516302a64b8360e21b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630a992e0c90611a94903090600401613127565b602060405180830381865afa158015611ab1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128d9190613c09565b33600090815260016020526040812080548391908390611af6908490613628565b90915550506001600160a01b0383166000818152600160205260409081902080548501905551339060008051602061412c83398151915290611b39908690613038565b60405180910390a350600192915050565b8380421115611b6c57604051630407b05b60e31b815260040160405180910390fd5b6000611b7a89898989612ae0565b9050600060018287878760405160008152602001604052604051611ba19493929190613c2a565b6020604051602081039080840390855afa158015611bc3573d6000803e3d6000fd5b505050602060405103519050896001600160a01b0316816001600160a01b031614611c0157604051638baa579f60e01b815260040160405180910390fd5b6001600160a01b038116611c2857604051638baa579f60e01b815260040160405180910390fd5b611c338a8a8a612846565b50505050505050505050565b6060611c496121d1565b611cb460405180610140016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600060ff168152602001606081525090565b611cc087890189613c52565b60ff166101008301526001600160a01b03166020820152611cdf612203565b606083019081526040808401928352306000908152600160205290812054608085015291519051611d119190836125c8565b60a08401819052909150600003611d2757600080fd5b611d4882604001518360800151611d3e919061363f565b8360a00151900490565b60c083015260608201516080830151611d6491611d3e9161363f565b60e08301526080820151611d799030906128ae565b611db27f000000000000000000000000000000000000000000000000000000000000000083602001518460c001518561010001516129c8565b611deb7f000000000000000000000000000000000000000000000000000000000000000083602001518460e001518561010001516129c8565b60c082015160408301805191909103905260e08201516060830180519190910390526001600160a01b03861615611ec957611e2587612458565b6001600160a01b03168252604080516020601f870181900481028201810190925285815290869086908190840183828082843760009201919091525050505061012083015260405163109ea27d60e31b81526001600160a01b038716906384f513e890611e96908590600401613d4e565b600060405180830381600087803b158015611eb057600080fd5b505af1158015611ec4573d6000803e3d6000fd5b505050505b611edb826040015183606001516127fe565b8015611ef757611ef38260400151836060015161236d565b600b555b6040805160028082526060820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081611f0d57905050925060405180604001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018360c0015181525083600081518110611f8b57611f8b6139e6565b602002602001018190525060405180604001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018360e0015181525083600181518110611feb57611feb6139e6565b602002602001018190525081602001516001600160a01b0316336001600160a01b03167fd175a80c109434bb89948928ab2475a6647c94244cb70002197896423c8833638460c001518560e0015186608001516040516111c1939291906137f8565b600954600a54600091907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b039081169087161483816120b3577f00000000000000000000000000000000000000000000000000000000000000006120d5565b7f00000000000000000000000000000000000000000000000000000000000000005b90506120f36120e5878a84612516565b62ffffff168886868661290d565b5098975050505050505050565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b1790529051600091606091839182916001600160a01b0387169161214891613d81565b600060405180830381855afa9150503d8060008114612183576040519150601f19603f3d011682016040523d82523d6000602084013e612188565b606091505b509150915081156121b4576001818060200190518101906121a99190613de5565b935093505050915091565b600060405180602001604052806000815250935093505050915091565b6002600854036121fc5760405162461bcd60e51b81526004016121f390613e20565b60405180910390fd5b6002600855565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f7888aec7f0000000000000000000000000000000000000000000000000000000000000000306040518363ffffffff1660e01b8152600401612274929190613e5b565b602060405180830381865afa158015612291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b59190613e81565b604051633de222bb60e21b81529092506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90612326907f0000000000000000000000000000000000000000000000000000000000000000903090600401613e5b565b602060405180830381865afa158015612343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123679190613e81565b90509091565b60006001600160801b0383111561239757604051631a93c68960e11b815260040160405180910390fd5b6001600160801b038211156123bf57604051631a93c68960e11b815260040160405180910390fd5b610b976123cc838561363f565b70ffffffffffffffffffffffffffffffffff811160071b81811c68ffffffffffffffffff1060061b1781811c64ffffffffff1060051b1781811c62ffffff1060041b1781811c620100000160b5600192831c1b0260121c80830401811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b60006001600160a01b03821615612512576001600160a01b038216331461251257604051632af3bd5560e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063abcef554906124c5903390600401613127565b602060405180830381865afa1580156124e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125069190613eb5565b61251257506000919050565b5090565b6000612533848484604051806020016040528060008152506118e5565b949350505050565b60008083600003612551575060009050806125bd565b848610612589576125826125658688613628565b61256f908a61363f565b61257d620186a0600261363f565b900490565b90506125bd565b600083612596868961363f565b6125a0919061368c565b90506125b96125af828a613628565b61256f908b61363f565b9250505b965096945050505050565b600080600054905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634ccb20c06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612630573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126549190613ee1565b600b546001600160a01b038216151594509091508015612797578315612791578460000361268957612686878761236d565b94505b8085111561278c57600061269b611a45565b62ffffff1690506000816126af8489613628565b6126b9908761363f565b6126c3919061363f565b905060006126d1848461363f565b886126df85620186a0613628565b6126e9919061363f565b6126f3919061365e565b90506000612701828461368c565b905080156127875761271386826127a1565b604051631087d04360e31b81526001600160a01b0387169063843e82189061274690600190309086908a90600401613f17565b600060405180830381600087803b15801561276057600080fd5b505af1158015612774573d6000803e3d6000fd5b505050508087612784919061365e565b96505b505050505b612797565b6000600b555b5050935093915050565b806000808282546127b2919061365e565b90915550506001600160a01b0382166000818152600160205260408082208054850190555160008051602061412c833981519152906127f2908590613038565b60405180910390a35050565b600a81905560098290556040517fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a9061283a90849084906130b5565b60405180910390a15050565b6001600160a01b0380841660008181526002602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906128a1908590613038565b60405180910390a3505050565b6001600160a01b038216600090815260016020526040812080548392906128d6908490613628565b90915550506000805482900381556040516001600160a01b0384169060008051602061412c833981519152906127f2908590613038565b6000808560000361292157600091506129be565b600061293088620186a0613628565b61293a908861363f565b9050612952612949898961363f565b620186a0900490565b9150831561298d5780612968620186a08861363f565b612972919061365e565b61297c868361363f565b612986919061368c565b92506129bc565b8061299b620186a08761363f565b6129a5919061365e565b6129af878361363f565b6129b9919061368c565b92505b505b9550959350505050565b8060ff16600003612a5a576040516317d5759960e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063beabacc890612a2390879087908790600401613f61565b600060405180830381600087803b158015612a3d57600080fd5b505af1158015612a51573d6000803e3d6000fd5b50505050612ada565b604051636cb568c160e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636cb568c190612aac908790879087908790600401613f7c565b600060405180830381600087803b158015612ac657600080fd5b505af1158015611270573d6000803e3d6000fd5b50505050565b6000612aea61127a565b6001600160a01b038616600090815260036020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c992899289928992909190612b3883613fb1565b9190505587604051602001612b5296959493929190613fcb565b60405160208183030381529060405280519060200120604051602001612b7992919061401a565b604051602081830303815290604052805190602001209050949350505050565b600080612ba68484612e09565b9050846001600160a01b0316816001600160a01b031603612bda576001600160a01b03811615612bda576001915050610b97565b600080866001600160a01b0316631626ba7e60e01b8787604051602401612c0292919061404b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612c409190613d81565b600060405180830381855afa9150503d8060008114612c7b576040519150601f19603f3d011682016040523d82523d6000602084013e612c80565b606091505b5091509150818015612c93575080516020145b8015612cba57508051630b135d3f60e11b90612cb89083016020908101908401613e81565b145b979650505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6004604051612cf791906140dd565b604051908190038120612d3392917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc690469030906020016140e9565b60405160208183030381529060405280519060200120905090565b600084600003612d605750600061197d565b8115612dbb57612d7386620186a0613628565b612d7d8686613628565b612d87919061363f565b620186a0612d95878661363f565b612d9f919061363f565b612da9919061368c565b612db490600161365e565b905061197d565b612dc886620186a0613628565b612dd28685613628565b612ddc919061363f565b620186a0612dea878761363f565b612df4919061363f565b612dfe919061368c565b610a1090600161365e565b60008151604114612e1c5750600061055b565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612e62576000935050505061055b565b60018682858560405160008152602001604052604051612e859493929190613c2a565b6020604051602081039080840390855afa158015612ea7573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b6001600160e01b031981165b8114612ed357600080fd5b50565b803561055b81612ebc565b600060208284031215612ef657612ef6600080fd5b60006125338484612ed6565b8015155b82525050565b6020810161055b8284612f02565b60008083601f840112612f2f57612f2f600080fd5b50813567ffffffffffffffff811115612f4a57612f4a600080fd5b602083019150836001820283011115612f6557612f65600080fd5b9250929050565b60006001600160a01b03821661055b565b612ec881612f6c565b803561055b81612f7d565b60008060008060008060808789031215612fad57612fad600080fd5b863567ffffffffffffffff811115612fc757612fc7600080fd5b612fd389828a01612f1a565b96509650506020612fe689828a01612f86565b9450506040612ff789828a01612f86565b935050606087013567ffffffffffffffff81111561301757613017600080fd5b61302389828a01612f1a565b92509250509295509295509295565b80612f06565b6020810161055b8284613032565b60005b83811015613061578181015183820152602001613049565b83811115612ada5750506000910152565b600061307c825190565b808452602084019350613093818560208601613046565b601f01601f19169290920192915050565b60208082528101610b978184613072565b604081016130c38285613032565b610b976020830184613032565b80612ec8565b803561055b816130d0565b600080604083850312156130f7576130f7600080fd5b60006131038585612f86565b9250506020613114858286016130d6565b9150509250929050565b612f0681612f6c565b6020810161055b828461311e565b60008060006060848603121561314d5761314d600080fd5b60006131598686612f86565b935050602061316a86828701612f86565b925050604061317b868287016130d6565b9150509250925092565b80516040830190613196848261311e565b506020820151612ada6020850182613032565b6040810161055b8284613185565b60008060008060008060a087890312156131d3576131d3600080fd5b60006131df8989612f86565b96505060206131f089828a01612f86565b955050604061320189828a016130d6565b945050606061321289828a016130d6565b935050608087013567ffffffffffffffff81111561301757613017600080fd5b60ff8116612f06565b6020810161055b8284613232565b6000613255838361311e565b505060200190565b6000613267825190565b80845260209384019383018060005b8381101561329b57815161328a8882613249565b975060208301925050600101613276565b509495945050505050565b60208082528101610b97818461325d565b6000602082840312156132cc576132cc600080fd5b60006125338484612f86565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff82111715613314576133146132d8565b6040525050565b600061332660405190565b905061333282826132ee565b919050565b600067ffffffffffffffff821115613351576133516132d8565b601f19601f83011660200192915050565b82818337506000910152565b600061338161337c84613337565b61331b565b90508281526020810184848401111561339c5761339c600080fd5b6133a7848285613362565b509392505050565b600082601f8301126133c3576133c3600080fd5b813561253384826020860161336e565b600080600080608085870312156133ec576133ec600080fd5b60006133f88787612f86565b945050602061340987828801612f86565b935050604061341a87828801612f86565b925050606085013567ffffffffffffffff81111561343a5761343a600080fd5b613446878288016133af565b91505092959194509250565b62ffffff8116612f06565b6020810161055b8284613452565b60008060006060848603121561348357613483600080fd5b600061348f8686612f86565b93505060206134a0868287016130d6565b925050604061317b86828701612f86565b61ffff8116612f06565b6020810161055b82846134b1565b60ff8116612ec8565b803561055b816134c9565b600080600080600080600060e0888a0312156134fb576134fb600080fd5b60006135078a8a612f86565b97505060206135188a828b01612f86565b96505060406135298a828b016130d6565b955050606061353a8a828b016130d6565b945050608061354b8a828b016134d2565b93505060a061355c8a828b016130d6565b92505060c061356d8a828b016130d6565b91505092959891949750929550565b6000806040838503121561359257613592600080fd5b600061359e8585612f86565b925050602061311485828601612f86565b60006135bb8383613185565b505060400190565b60006135cd825190565b80845260209384019383018060005b8381101561329b5781516135f088826135af565b9750602083019250506001016135dc565b60208082528101610b9781846135c3565b634e487b7160e01b600052601160045260246000fd5b60008282101561363a5761363a613612565b500390565b600081600019048311821515161561365957613659613612565b500290565b6000821982111561367157613671613612565b500190565b634e487b7160e01b600052601260045260246000fd5b60008261369b5761369b613676565b500490565b80516000906102008401906136b5858261311e565b5060208301516136c8602086018261311e565b5060408301516136db6040860182613032565b5060608301516136ee6060860182613032565b5060808301516137016080860182613032565b5060a083015161371460a0860182613032565b5060c083015161372760c0860182613032565b5060e083015161373a60e0860182613032565b5061010083015161374f610100860182613032565b50610120830151613764610120860182613032565b50610140830151613779610140860182613032565b5061016083015161378e610160860182613032565b506101808301516137a3610180860182613032565b506101a08301516137b86101a0860182613032565b506101c08301516137cd6101c0860182613452565b506101e08301518482036101e086015261197d8282613072565b60208082528101610b9781846136a0565b606081016138068286613032565b6138136020830185613032565b6125336040830184613032565b634e487b7160e01b600052602260045260246000fd5b60028104600182168061384a57607f821691505b60208210810361385c5761385c613820565b50919050565b60008060006060848603121561387a5761387a600080fd5b60006138868686612f86565b935050602061389786828701612f86565b925050604061317b868287016134d2565b80516000906102008401906138bd858261311e565b5060208301516138d0602086018261311e565b5060408301516138e3604086018261311e565b5060608301516138f6606086018261311e565b5060808301516139096080860182613032565b5060a083015161391c60a0860182613032565b5060c083015161392f60c0860182613032565b5060e083015161394260e0860182613032565b50610100830151613957610100860182613032565b5061012083015161396c610120860182613032565b50610140830151613981610140860182613032565b50610160830151613996610160860182613032565b506101808301516139ab610180860182613032565b506101a08301516139c06101a0860182613452565b506101c08301516137cd6101c0860182613232565b60208082528101610b9781846138a8565b634e487b7160e01b600052603260045260246000fd5b600061055b613a088381565b90565b612f06816139fc565b60808101613a228287613032565b613a2f6020830186613a0b565b613a3c6040830185613a0b565b61197d6060830184613032565b60808101613a578287613a0b565b613a646020830186613032565b613a716040830185613032565b61197d6060830184613a0b565b80516000906101c0840190613a93858261311e565b506020830151613aa6602086018261311e565b506040830151613ab9604086018261311e565b506060830151613acc606086018261311e565b506080830151613adf6080860182613032565b5060a0830151613af260a0860182613032565b5060c0830151613b0560c0860182613032565b5060e0830151613b1860e0860182613032565b50610100830151613b2d610100860182613032565b50610120830151613b42610120860182613032565b50610140830151613b57610140860182613032565b50610160830151613b6c610160860182613452565b50610180830151613b81610180860182613232565b506101a08301518482036101a086015261197d8282613072565b60208082528101610b978184613a7e565b60a08101613bba828861311e565b613bc7602083018761311e565b613bd4604083018661311e565b613be1606083018561311e565b8181036080830152612cba8184613072565b62ffffff8116612ec8565b805161055b81613bf3565b600060208284031215613c1e57613c1e600080fd5b60006125338484613bfe565b60808101613c388287613032565b613c456020830186613232565b613a3c6040830185613032565b60008060408385031215613c6857613c68600080fd5b6000613c748585612f86565b9250506020613114858286016134d2565b8051600090610140840190613c9a858261311e565b506020830151613cad602086018261311e565b506040830151613cc06040860182613032565b506060830151613cd36060860182613032565b506080830151613ce66080860182613032565b5060a0830151613cf960a0860182613032565b5060c0830151613d0c60c0860182613032565b5060e0830151613d1f60e0860182613032565b50610100830151613d34610100860182613232565b5061012083015184820361012086015261197d8282613072565b60208082528101610b978184613c85565b6000613d69825190565b613d77818560208601613046565b9290920192915050565b6000610b978284613d5f565b6000613d9b61337c84613337565b905082815260208101848484011115613db657613db6600080fd5b6133a7848285613046565b600082601f830112613dd557613dd5600080fd5b8151612533848260208601613d8d565b600060208284031215613dfa57613dfa600080fd5b815167ffffffffffffffff811115613e1457613e14600080fd5b61253384828501613dc1565b6020808252810161055b81601f81527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00602082015260400190565b60408101613e69828561311e565b610b97602083018461311e565b805161055b816130d0565b600060208284031215613e9657613e96600080fd5b60006125338484613e76565b801515612ec8565b805161055b81613ea2565b600060208284031215613eca57613eca600080fd5b60006125338484613eaa565b805161055b81612f7d565b600060208284031215613ef657613ef6600080fd5b60006125338484613ed6565b600061ffff821661055b565b612f0681613f02565b60a08101613f258287613f0e565b613f32602083018661311e565b613f3f6040830185613032565b613f4c6060830184613032565b81810360808301526000815260208101610a10565b60608101613f6f828661311e565b613813602083018561311e565b60808101613f8a828761311e565b613f97602083018661311e565b613fa46040830185613032565b61197d6060830184613232565b60006000198203613fc457613fc4613612565b5060010190565b60c08101613fd98289613032565b613fe6602083018861311e565b613ff3604083018761311e565b6140006060830186613032565b61400d6080830185613032565b612cba60a0830184613032565b61190160f01b815260020160006140318285613032565b6020820191506140418284613032565b5060200192915050565b604081016140598285613032565b81810360208301526125338184613072565b6000815461407881613836565b60018216801561408f57600181146140a4576140d4565b60ff19831686528115158202860193506140d4565b60008581526020902060005b838110156140cc578154888201526001909101906020016140b0565b838801955050505b50505092915050565b6000610b97828461406b565b60a081016140f78288613a0b565b6141046020830187613032565b6141116040830186613a0b565b61411e6060830185613032565b610a10608083018461311e56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212209d4df6080488c965e85c8d46a748d3e9c678e134194f5c0fad6ef2903c78217b64736f6c634300080f0033a26469706673582212204b619fda80c15b4e75b8d2761286fe37fd0165cae1297695220dd54ad6154e8764736f6c634300080f0033000000000000000000000000608cb7c3168427091f5994a45baf12083964b4a3
Deployed Bytecode
0x60806040523480156200001157600080fd5b50600436106200005e5760003560e01c806313b8683f14620000635780634625a94d1462000092578063531aa03e14620000b8578063d039f62214620000ec578063ee97f7f31462000105575b600080fd5b6200007a62000074366004620005fa565b6200012d565b6040516200008991906200066c565b60405180910390f35b620000a9620000a3366004620006a3565b62000264565b60405162000089919062000753565b6200007a620000c936600462000763565b60006020818152928152604080822090935290815220546001600160a01b031681565b620000f66200030e565b60405162000089919062000810565b6200007a7f000000000000000000000000608cb7c3168427091f5994a45baf12083964b4a381565b600080806200013f8486018662000763565b91509150806001600160a01b0316826001600160a01b03160362000176576040516333910aef60e11b815260040160405180910390fd5b816001600160a01b0316816001600160a01b031610156200019357905b6001600160a01b038216620001bb576040516333910aef60e11b815260040160405180910390fd5b620001c78282620003a8565b6001600160a01b0380841660008181526020818152604080832087861680855290835281842080549688166001600160a01b03199788168117909155848452828520868652909352928190208054909516909117909355915192955090917f9c5d829b9b23efc461f9aeef91979ec04bb903feb3bee4f26d22114abfc7335b90620002549087906200066c565b60405180910390a3505092915050565b604051634625a94d60e01b81526000906001600160a01b037f000000000000000000000000608cb7c3168427091f5994a45baf12083964b4a31690634625a94d90620002bf908a908a908a908a908a908a906004016200085c565b602060405180830381865afa158015620002dd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620003039190620008d3565b979650505050505050565b6060600180546200031f9062000916565b80601f01602080910402602001604051908101604052809291908181526020018280546200034d9062000916565b80156200039e5780601f1062000372576101008083540402835291602001916200039e565b820191906000526020600020905b8154815290600101906020018083116200038057829003601f168201915b5050505050905090565b6040516370a0823160e01b81526000906001600160a01b038416906370a0823190620003d99030906004016200066c565b602060405180830381865afa158015620003f7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041d91906200095a565b506040516370a0823160e01b81526001600160a01b038316906370a08231906200044c9030906004016200066c565b602060405180830381865afa1580156200046a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200049091906200095a565b5060008383604051602001620004a89291906200097f565b60408051601f1981840301815291905290506001620004c8828262000a6b565b50805160208201206040518190620004e09062000594565b8190604051809103906000f590508015801562000501573d6000803e3d6000fd5b5060405163784198d960e01b81529093506001600160a01b037f000000000000000000000000608cb7c3168427091f5994a45baf12083964b4a3169063784198d99062000558908690600190879060040162000b54565b600060405180830381600087803b1580156200057357600080fd5b505af115801562000588573d6000803e3d6000fd5b50505050505092915050565b614d0d8062000b9183390190565b60008083601f840112620005b957620005b9600080fd5b50813567ffffffffffffffff811115620005d657620005d6600080fd5b602083019150836001820283011115620005f357620005f3600080fd5b9250929050565b60008060208385031215620006125762000612600080fd5b823567ffffffffffffffff8111156200062e576200062e600080fd5b6200063c85828601620005a2565b92509250509250929050565b60006001600160a01b0382165b92915050565b620006668162000648565b82525050565b602081016200065582846200065b565b620006878162000648565b81146200069357600080fd5b50565b803562000655816200067c565b60008060008060008060a08789031215620006c157620006c1600080fd5b6000620006cf898962000696565b9650506020620006e289828a0162000696565b9550506040620006f589828a0162000696565b94505060606200070889828a0162000696565b935050608087013567ffffffffffffffff8111156200072a576200072a600080fd5b6200073889828a01620005a2565b92509250509295509295509295565b62ffffff811662000666565b6020810162000655828462000747565b600080604083850312156200077b576200077b600080fd5b600062000789858562000696565b92505060206200079c8582860162000696565b9150509250929050565b60005b83811015620007c3578181015183820152602001620007a9565b83811115620007d3576000848401525b50505050565b6000620007e4825190565b808452602084019350620007fd818560208601620007a6565b601f19601f8201165b9093019392505050565b60208082528101620008238184620007d9565b9392505050565b82818337506000910152565b81835260006020840193506200084e8385846200082a565b601f19601f84011662000806565b60a081016200086c82896200065b565b6200087b60208301886200065b565b6200088a60408301876200065b565b6200089960608301866200065b565b8181036080830152620008ae81848662000836565b98975050505050505050565b62ffffff811662000687565b80516200065581620008ba565b600060208284031215620008ea57620008ea600080fd5b6000620008f88484620008c6565b949350505050565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806200092b57607f821691505b60208210810362000940576200094062000900565b50919050565b8062000687565b8051620006558162000946565b600060208284031215620009715762000971600080fd5b6000620008f884846200094d565b604081016200098f82856200065b565b6200082360208301846200065b565b634e487b7160e01b600052604160045260246000fd5b600062000655620009c28381565b90565b620009d083620009b4565b81546008840282811b60001990911b908116901990911617825550505050565b6000620009ff818484620009c5565b505050565b8181101562000a235762000a1a600082620009f0565b60010162000a04565b5050565b601f821115620009ff576000818152602090206020601f8501048101602085101562000a505750805b62000a646020601f86010483018262000a04565b5050505050565b815167ffffffffffffffff81111562000a885762000a886200099e565b62000a94825462000916565b62000aa182828562000a27565b6020601f83116001811462000ad8576000841562000abf5750858201515b600019600886021c198116600286021786555062000b34565b600085815260208120601f198616915b8281101562000b0a578885015182556020948501946001909201910162000ae8565b8683101562000b275784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b600061ffff821662000655565b620006668162000b3c565b6060810162000b6482866200065b565b62000b73602083018562000b49565b818103604083015262000b878184620007d9565b9594505050505056fe61012060405260126080523480156200001757600080fd5b5060016008819055506000336001600160a01b031663d039f6226040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000061573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200008b919081019062000597565b905060008082806020019051810190620000a6919062000611565b915091506000336001600160a01b031663ee97f7f36040518163ffffffff1660e01b8152600401602060405180830381865afa158015620000eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000111919062000654565b9050806001600160a01b031660a0816001600160a01b031681525050806001600160a01b031663fbfa77cf6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200016c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000192919062000654565b6001600160a01b0390811660c05282811661010052831660e052600080620001c685620002c2602090811b6200210017901c565b91509150600080620001e386620002c260201b620021001760201c565b91509150838015620001f25750815b1562000251576200024b8382604051602001620002119291906200069e565b604051602081830303815290604052848360405160200162000235929190620006f3565b60408051601f198184030181529190526200039a565b620002b4565b620002b46040518060400160405280601381526020017f53796e635377617020436c6173736963204c500000000000000000000000000081525060405180604001604052806004815260200163063534c560e41b8152506200039a60201b60201c565b505050505050505062000a13565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b1790529051600091606091839182916001600160a01b038716916200030c9162000730565b600060405180830381855afa9150503d806000811462000349576040519150601f19603f3d011682016040523d82523d6000602084013e6200034e565b606091505b509150915081156200037d5760018180602001905181019062000372919062000597565b935093505050915091565b600060405180602001604052806000815250935093505050915091565b6004620003a8838262000842565b506005620003b7828262000842565b5046600655620003c6620003cd565b6007555050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60046040516200040191906200098c565b6040519081900381206200043f92917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69046903090602001620009bd565b60405160208183030381529060405280519060200120905090565b634e487b7160e01b600052604160045260246000fd5b601f19601f83011681018181106001600160401b03821117156200049857620004986200045a565b6040525050565b6000620004ab60405190565b9050620004b9828262000470565b919050565b60006001600160401b03821115620004da57620004da6200045a565b601f19601f83011660200192915050565b60005b8381101562000508578181015183820152602001620004ee565b8381111562000518576000848401525b50505050565b6000620005356200052f84620004be565b6200049f565b905082815260208101848484011115620005525762000552600080fd5b6200055f848285620004eb565b509392505050565b600082601f8301126200057d576200057d600080fd5b81516200058f8482602086016200051e565b949350505050565b600060208284031215620005ae57620005ae600080fd5b81516001600160401b03811115620005c957620005c9600080fd5b6200058f8482850162000567565b60006001600160a01b0382165b92915050565b620005f581620005d7565b81146200060157600080fd5b50565b8051620005e481620005ea565b60008060408385031215620006295762000629600080fd5b600062000637858562000604565b92505060206200064a8582860162000604565b9150509250929050565b6000602082840312156200066b576200066b600080fd5b60006200058f848462000604565b600062000684825190565b62000694818560208601620004eb565b9290920192915050565b68029bcb731a9bbb0b8160bd1b81526009016000620006be828562000679565b602f60f81b81526001019150620006d6828462000679565b6a020436c6173736963204c560ac1b81529150600b82016200058f565b600062000701828562000679565b602f60f81b8152600101915062000719828462000679565b6402063534c560dc1b81529150600582016200058f565b60006200073e828462000679565b9392505050565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806200077057607f821691505b60208210810362000785576200078562000745565b50919050565b6000620005e4620007998381565b90565b620007a7836200078b565b81546008840282811b60001990911b908116901990911617825550505050565b6000620007d68184846200079c565b505050565b81811015620007fa57620007f1600082620007c7565b600101620007db565b5050565b601f821115620007d6576000818152602090206020601f85010481016020851015620008275750805b6200083b6020601f860104830182620007db565b5050505050565b81516001600160401b038111156200085e576200085e6200045a565b6200086a82546200075b565b62000877828285620007fe565b6020601f831160018114620008ae5760008415620008955750858201515b600019600886021c19811660028602178655506200090a565b600085815260208120601f198616915b82811015620008e05788850151825560209485019460019092019101620008be565b86831015620008fd5784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b6000815462000921816200075b565b6001821680156200093b5760018114620009515762000983565b60ff198316865281151582028601935062000983565b60008581526020902060005b838110156200097b578154888201526001909101906020016200095d565b838801955050505b50505092915050565b60006200073e828462000912565b620009a5816200078b565b82525050565b80620009a5565b620009a581620005d7565b60a08101620009cd82886200099a565b620009dc6020830187620009ab565b620009eb60408301866200099a565b620009fa6060830185620009ab565b62000a096080830184620009b2565b9695505050505050565b60805160a05160c05160e0516101005161418162000b8c6000396000818161042e015281816106fd0152818161073701528181610d4201528181610da401528181610e6801528181610f1401528181610f700152818161130f015281816114da01528181611513015281816115fe01528181611644015281816119fb01528181611db701528181611fa3015281816120b501526122fc015260008181610288015281816106dc0152818161075801528181610d8301528181610ddf01528181610ece01528181610f3501528181610ffd015281816112bb01528181611478015281816114b9015281816116650152818161169e0152818161199f015281816119d501528181611d7e01528181611f43015281816120590152818161208f01526122370152600081816104da01528181612208015281816122cf015281816129ea0152612a71015260008181610493015281816118ff01528181611a5f0152818161249001526125d40152600061030d01526141816000f3fe608060405234801561001057600080fd5b50600436106101f05760003560e01c806370a082311161010f578063b1dd61b6116100a2578063ee97f7f311610071578063ee97f7f31461048e578063f66eab5b146104b5578063fbfa77cf146104d5578063ff9c8ac6146104fc57600080fd5b8063b1dd61b614610414578063d21220a714610429578063d505accf14610450578063dd62ed3e1461046357600080fd5b806395d89b41116100de57806395d89b41146103de578063a287c795146103e6578063a5a41031146103f9578063a9059cbb1461040157600080fd5b806370a082311461036b5780637132bb7f1461038b5780637ecebe001461039e5780638b4c5470146103be57600080fd5b806323b872dd116101875780633644e515116101565780633644e5151461033c578063443cb4bc146103445780635a76f25e1461034d57806367e4ac2c1461035657600080fd5b806323b872dd146102c057806327b0bcea146102d35780632c0198cc146102f3578063313ce5671461030857600080fd5b80630902f1ac116101c35780630902f1ac1461025c578063095ea7b3146102705780630dfe16811461028357806318160ddd146102b757600080fd5b806301ffc9a7146101f557806303e7286a1461021e57806306fdde031461023e57806307f293f714610253575b600080fd5b610208610203366004612ee1565b61050f565b6040516102159190612f0c565b60405180910390f35b61023161022c366004612f91565b610561565b6040516102159190613038565b610246610a1a565b60405161021591906130a4565b610231600b5481565b600954600a546040516102159291906130b5565b61020861027e3660046130e1565b610aa8565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b6040516102159190613127565b61023160005481565b6102086102ce366004613135565b610abe565b6102e66102e1366004612f91565b610b9e565b60405161021591906131a9565b6103066103013660046131b7565b6111d5565b005b61032f7f000000000000000000000000000000000000000000000000000000000000000081565b604051610215919061323b565b61023161127a565b61023160095481565b610231600a5481565b61035e611299565b60405161021591906132a6565b6102316103793660046132b7565b60016020526000908152604090205481565b6102e6610399366004612f91565b611364565b6102316103ac3660046132b7565b60036020526000908152604090205481565b6103d16103cc3660046133d3565b6118e5565b604051610215919061345d565b610246611986565b6102316103f436600461346b565b611993565b6103d1611a45565b61020861040f3660046130e1565b611ad5565b61041c600181565b60405161021591906134bb565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b61030661045e3660046134dd565b611b4a565b61023161047136600461357c565b600260209081526000928352604080842090915290825290205481565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b6104c86104c3366004612f91565b611c3f565b6040516102159190613601565b6102aa7f000000000000000000000000000000000000000000000000000000000000000081565b61023161050a36600461346b565b61204d565b60006001600160e01b031982166301ffc9a760e01b148061054057506001600160e01b0319821663d505accf60e01b145b8061055b57506001600160e01b03198216630b00663360e21b145b92915050565b600061056b6121d1565b61060260405180610200016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001606081525090565b61060e878901896132b7565b6001600160a01b03166020820152600954600a5460608301526040820152610634612203565b60a083018190526080830182905261064c919061236d565b610140820152604081015160808201516106669190613628565b60c0820152606081015160a082015161067f9190613628565b60e082015261068d86612458565b9550600081604001516000146106c3576106be82606001518360c001516106b4919061363f565b8360400151900490565b6106c6565b60005b60e08301519091508111801561073157610721887f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101c0840152610788565b61077c887f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101c08401525b6107b0836101c0015162ffffff168460c001518560e00151858760400151886060015161253b565b61012085015261010084018190526040840180516107cf90839061365e565b9052506101208301516060840180516107e990839061365e565b90525060408301516060840151610800919061236d565b610160840181905260009061081890829081906125c8565b6101808601819052909150600003610855576103e884610140015161083d9190613628565b6101a085015261085060006103e86127a1565b61088d565b610160840151610180850151610140860151610872908390613628565b61087c919061363f565b610886919061368c565b6101a08501525b836101a001516000036108b357604051633489be7560e21b815260040160405180910390fd5b6108c68460200151856101a001516127a1565b6001600160a01b0388161561097a576001600160a01b0389168452604080516020601f89018190048102820181019092528781529088908890819084018382808284376000920191909152505050506101e0850152604051630204997360e41b81526001600160a01b038916906320499730906109479087906004016137e7565b600060405180830381600087803b15801561096157600080fd5b505af1158015610975573d6000803e3d6000fd5b505050505b61098c84608001518560a001516127fe565b801561099c57610140840151600b555b83602001516001600160a01b0316336001600160a01b03167fa8137fff86647d8a402117b9c5dbda627f721d3773338fb9678c83e54ed390808660c001518760e00151886101a001516040516109f4939291906137f8565b60405180910390a35050506101a001519050610a106001600855565b9695505050505050565b60048054610a2790613836565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5390613836565b8015610aa05780601f10610a7557610100808354040283529160200191610aa0565b820191906000526020600020905b815481529060010190602001808311610a8357829003601f168201915b505050505081565b6000610ab5338484612846565b50600192915050565b6001600160a01b03831660009081526002602090815260408083203384529091528120546000198114610b1a57610af58382613628565b6001600160a01b03861660009081526002602090815260408083203384529091529020555b6001600160a01b03851660009081526001602052604081208054859290610b42908490613628565b90915550506001600160a01b038085166000818152600160205260409081902080548701905551909187169060008051602061412c83398151915290610b89908790613038565b60405180910390a360019150505b9392505050565b6040805180820190915260008082526020820152610bba6121d1565b610c6660405180610200016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b610c7287890189613862565b60ff166101c08401526001600160a01b039081166020840152166060820152610c99612203565b60a08301908152608083019182523060009081526001602052604081205460c085015291519051610ccb9190836125c8565b60e08401819052909150600003610ce157600080fd5b610d0282608001518360c00151610cf8919061363f565b8360e00151900490565b61010083015260a082015160c0830151610d1f91610cf89161363f565b61012083015260c0820151610d359030906128ae565b610d3e87612458565b96507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682606001516001600160a01b031603610ecc57610dc8877f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101a083018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408401526101008301516080840151610e3c929190610e20908290613628565b8561012001518660a00151610e359190613628565b600161290d565b610180840152610160830181905261012083018051610e5c90839061365e565b91508181525050610e9d7f00000000000000000000000000000000000000000000000000000000000000008360200151846101200151856101c001516129c8565b6101208201516101408301819052600061010084015260a083018051610ec4908390613628565b90525061105d565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031682606001516001600160a01b031614610f0e57600080fd5b610f59877f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101a083018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408401526101208301516101008401516080850151610fd1939291610fb591613628565b8561012001518660a00151610fca9190613628565b600061290d565b610180840152610160830181905261010083018051610ff190839061365e565b915081815250506110327f00000000000000000000000000000000000000000000000000000000000000008360200151846101000151856101c001516129c8565b61010082015161014083018190526000610120840152608083018051611059908390613628565b9052505b6001600160a01b03861615611111576001600160a01b0387168252604080516020601f87018190048102820181019092528581529086908690819084018382808284376000920191909152505050506101e0830152604051630eace54160e11b81526001600160a01b03871690631d59ca82906110de9085906004016139d5565b600060405180830381600087803b1580156110f857600080fd5b505af115801561110c573d6000803e3d6000fd5b505050505b61112382608001518360a001516127fe565b801561113f5761113b82608001518360a0015161236d565b600b555b604051806040016040528083606001516001600160a01b03168152602001836101400151815250925081602001516001600160a01b0316336001600160a01b03167fd175a80c109434bb89948928ab2475a6647c94244cb70002197896423c8833638461010001518561012001518660c001516040516111c1939291906137f8565b60405180910390a35050610a106001600855565b82804211156111f757604051630407b05b60e31b815260040160405180910390fd5b600061120588888888612ae0565b9050611248888286868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612b9992505050565b61126557604051638baa579f60e01b815260040160405180910390fd5b611270888888612846565b5050505050505050565b600060065446146112925761128d612cc5565b905090565b5060075490565b60408051600280825260608083018452926020830190803683370190505090507f0000000000000000000000000000000000000000000000000000000000000000816000815181106112ed576112ed6139e6565b60200260200101906001600160a01b031690816001600160a01b0316815250507f000000000000000000000000000000000000000000000000000000000000000081600181518110611341576113416139e6565b60200260200101906001600160a01b031690816001600160a01b03168152505090565b60408051808201909152600080825260208201526113806121d1565b61141e604051806101c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b61142a87890189613862565b60ff166101808401526001600160a01b039081166020840152166040820152600954600a5460a08301526080820152611461612203565b60e083015260c082015261147486612458565b95507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681604001516001600160a01b0316036115fc576114fe867f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101608201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166060820152608081015160c082015161154c9190613628565b8161010001818152505061157b81610160015162ffffff1682610100015183608001518460a00151600161290d565b610140830152610120820181905260e08201805161159a908390613628565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822926115ef926000918291613a14565b60405180910390a3611785565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681604001516001600160a01b03161461163e57600080fd5b611689867f00000000000000000000000000000000000000000000000000000000000000007f0000000000000000000000000000000000000000000000000000000000000000612516565b62ffffff166101608201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016606082015260a081015160e08201516116d79190613628565b8161010001818152505061170681610160015162ffffff1682610100015183608001518460a00151600061290d565b610140830152610120820181905260c082018051611725908390613628565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229261177c9260009291908390613a49565b60405180910390a35b60c08101516001600160801b0310156117b157604051631a93c68960e11b815260040160405180910390fd5b60e08101516001600160801b0310156117dd57604051631a93c68960e11b815260040160405180910390fd5b6117fb816060015182602001518361012001518461018001516129c8565b6001600160a01b038516156118af576001600160a01b0386168152604080516020601f86018190048102820181019092528481529085908590819084018382808284376000920191909152505050506101a082015260405163608dbcbb60e01b81526001600160a01b0386169063608dbcbb9061187c908490600401613b9b565b600060405180830381600087803b15801561189657600080fd5b505af11580156118aa573d6000803e3d6000fd5b505050505b6118c18160c001518260e001516127fe565b60608101516001600160a01b0316825261012001516020820152610a106001600855565b604051634625a94d60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690634625a94d9061193c9030908990899089908990600401613bac565b602060405180830381865afa158015611959573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061197d9190613c09565b95945050505050565b60058054610a2790613836565b600954600a54600091907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b039081169087161483816119f9577f0000000000000000000000000000000000000000000000000000000000000000611a1b565b7f00000000000000000000000000000000000000000000000000000000000000005b9050611a39611a2b87838b612516565b62ffffff1688868686612d4e565b98975050505050505050565b6040516302a64b8360e21b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690630a992e0c90611a94903090600401613127565b602060405180830381865afa158015611ab1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061128d9190613c09565b33600090815260016020526040812080548391908390611af6908490613628565b90915550506001600160a01b0383166000818152600160205260409081902080548501905551339060008051602061412c83398151915290611b39908690613038565b60405180910390a350600192915050565b8380421115611b6c57604051630407b05b60e31b815260040160405180910390fd5b6000611b7a89898989612ae0565b9050600060018287878760405160008152602001604052604051611ba19493929190613c2a565b6020604051602081039080840390855afa158015611bc3573d6000803e3d6000fd5b505050602060405103519050896001600160a01b0316816001600160a01b031614611c0157604051638baa579f60e01b815260040160405180910390fd5b6001600160a01b038116611c2857604051638baa579f60e01b815260040160405180910390fd5b611c338a8a8a612846565b50505050505050505050565b6060611c496121d1565b611cb460405180610140016040528060006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600060ff168152602001606081525090565b611cc087890189613c52565b60ff166101008301526001600160a01b03166020820152611cdf612203565b606083019081526040808401928352306000908152600160205290812054608085015291519051611d119190836125c8565b60a08401819052909150600003611d2757600080fd5b611d4882604001518360800151611d3e919061363f565b8360a00151900490565b60c083015260608201516080830151611d6491611d3e9161363f565b60e08301526080820151611d799030906128ae565b611db27f000000000000000000000000000000000000000000000000000000000000000083602001518460c001518561010001516129c8565b611deb7f000000000000000000000000000000000000000000000000000000000000000083602001518460e001518561010001516129c8565b60c082015160408301805191909103905260e08201516060830180519190910390526001600160a01b03861615611ec957611e2587612458565b6001600160a01b03168252604080516020601f870181900481028201810190925285815290869086908190840183828082843760009201919091525050505061012083015260405163109ea27d60e31b81526001600160a01b038716906384f513e890611e96908590600401613d4e565b600060405180830381600087803b158015611eb057600080fd5b505af1158015611ec4573d6000803e3d6000fd5b505050505b611edb826040015183606001516127fe565b8015611ef757611ef38260400151836060015161236d565b600b555b6040805160028082526060820190925290816020015b6040805180820190915260008082526020820152815260200190600190039081611f0d57905050925060405180604001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018360c0015181525083600081518110611f8b57611f8b6139e6565b602002602001018190525060405180604001604052807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018360e0015181525083600181518110611feb57611feb6139e6565b602002602001018190525081602001516001600160a01b0316336001600160a01b03167fd175a80c109434bb89948928ab2475a6647c94244cb70002197896423c8833638460c001518560e0015186608001516040516111c1939291906137f8565b600954600a54600091907f00000000000000000000000000000000000000000000000000000000000000006001600160a01b039081169087161483816120b3577f00000000000000000000000000000000000000000000000000000000000000006120d5565b7f00000000000000000000000000000000000000000000000000000000000000005b90506120f36120e5878a84612516565b62ffffff168886868661290d565b5098975050505050505050565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b1790529051600091606091839182916001600160a01b0387169161214891613d81565b600060405180830381855afa9150503d8060008114612183576040519150601f19603f3d011682016040523d82523d6000602084013e612188565b606091505b509150915081156121b4576001818060200190518101906121a99190613de5565b935093505050915091565b600060405180602001604052806000815250935093505050915091565b6002600854036121fc5760405162461bcd60e51b81526004016121f390613e20565b60405180910390fd5b6002600855565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663f7888aec7f0000000000000000000000000000000000000000000000000000000000000000306040518363ffffffff1660e01b8152600401612274929190613e5b565b602060405180830381865afa158015612291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122b59190613e81565b604051633de222bb60e21b81529092506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063f7888aec90612326907f0000000000000000000000000000000000000000000000000000000000000000903090600401613e5b565b602060405180830381865afa158015612343573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123679190613e81565b90509091565b60006001600160801b0383111561239757604051631a93c68960e11b815260040160405180910390fd5b6001600160801b038211156123bf57604051631a93c68960e11b815260040160405180910390fd5b610b976123cc838561363f565b70ffffffffffffffffffffffffffffffffff811160071b81811c68ffffffffffffffffff1060061b1781811c64ffffffffff1060051b1781811c62ffffff1060041b1781811c620100000160b5600192831c1b0260121c80830401811c80830401811c80830401811c80830401811c80830401811c80830401811c80830401901c908190048111900390565b60006001600160a01b03821615612512576001600160a01b038216331461251257604051632af3bd5560e21b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063abcef554906124c5903390600401613127565b602060405180830381865afa1580156124e2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906125069190613eb5565b61251257506000919050565b5090565b6000612533848484604051806020016040528060008152506118e5565b949350505050565b60008083600003612551575060009050806125bd565b848610612589576125826125658688613628565b61256f908a61363f565b61257d620186a0600261363f565b900490565b90506125bd565b600083612596868961363f565b6125a0919061368c565b90506125b96125af828a613628565b61256f908b61363f565b9250505b965096945050505050565b600080600054905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634ccb20c06040518163ffffffff1660e01b8152600401602060405180830381865afa158015612630573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126549190613ee1565b600b546001600160a01b038216151594509091508015612797578315612791578460000361268957612686878761236d565b94505b8085111561278c57600061269b611a45565b62ffffff1690506000816126af8489613628565b6126b9908761363f565b6126c3919061363f565b905060006126d1848461363f565b886126df85620186a0613628565b6126e9919061363f565b6126f3919061365e565b90506000612701828461368c565b905080156127875761271386826127a1565b604051631087d04360e31b81526001600160a01b0387169063843e82189061274690600190309086908a90600401613f17565b600060405180830381600087803b15801561276057600080fd5b505af1158015612774573d6000803e3d6000fd5b505050508087612784919061365e565b96505b505050505b612797565b6000600b555b5050935093915050565b806000808282546127b2919061365e565b90915550506001600160a01b0382166000818152600160205260408082208054850190555160008051602061412c833981519152906127f2908590613038565b60405180910390a35050565b600a81905560098290556040517fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a9061283a90849084906130b5565b60405180910390a15050565b6001600160a01b0380841660008181526002602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906128a1908590613038565b60405180910390a3505050565b6001600160a01b038216600090815260016020526040812080548392906128d6908490613628565b90915550506000805482900381556040516001600160a01b0384169060008051602061412c833981519152906127f2908590613038565b6000808560000361292157600091506129be565b600061293088620186a0613628565b61293a908861363f565b9050612952612949898961363f565b620186a0900490565b9150831561298d5780612968620186a08861363f565b612972919061365e565b61297c868361363f565b612986919061368c565b92506129bc565b8061299b620186a08761363f565b6129a5919061365e565b6129af878361363f565b6129b9919061368c565b92505b505b9550959350505050565b8060ff16600003612a5a576040516317d5759960e31b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063beabacc890612a2390879087908790600401613f61565b600060405180830381600087803b158015612a3d57600080fd5b505af1158015612a51573d6000803e3d6000fd5b50505050612ada565b604051636cb568c160e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636cb568c190612aac908790879087908790600401613f7c565b600060405180830381600087803b158015612ac657600080fd5b505af1158015611270573d6000803e3d6000fd5b50505050565b6000612aea61127a565b6001600160a01b038616600090815260036020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c992899289928992909190612b3883613fb1565b9190505587604051602001612b5296959493929190613fcb565b60405160208183030381529060405280519060200120604051602001612b7992919061401a565b604051602081830303815290604052805190602001209050949350505050565b600080612ba68484612e09565b9050846001600160a01b0316816001600160a01b031603612bda576001600160a01b03811615612bda576001915050610b97565b600080866001600160a01b0316631626ba7e60e01b8787604051602401612c0292919061404b565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051612c409190613d81565b600060405180830381855afa9150503d8060008114612c7b576040519150601f19603f3d011682016040523d82523d6000602084013e612c80565b606091505b5091509150818015612c93575080516020145b8015612cba57508051630b135d3f60e11b90612cb89083016020908101908401613e81565b145b979650505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6004604051612cf791906140dd565b604051908190038120612d3392917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc690469030906020016140e9565b60405160208183030381529060405280519060200120905090565b600084600003612d605750600061197d565b8115612dbb57612d7386620186a0613628565b612d7d8686613628565b612d87919061363f565b620186a0612d95878661363f565b612d9f919061363f565b612da9919061368c565b612db490600161365e565b905061197d565b612dc886620186a0613628565b612dd28685613628565b612ddc919061363f565b620186a0612dea878761363f565b612df4919061363f565b612dfe919061368c565b610a1090600161365e565b60008151604114612e1c5750600061055b565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612e62576000935050505061055b565b60018682858560405160008152602001604052604051612e859493929190613c2a565b6020604051602081039080840390855afa158015612ea7573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b6001600160e01b031981165b8114612ed357600080fd5b50565b803561055b81612ebc565b600060208284031215612ef657612ef6600080fd5b60006125338484612ed6565b8015155b82525050565b6020810161055b8284612f02565b60008083601f840112612f2f57612f2f600080fd5b50813567ffffffffffffffff811115612f4a57612f4a600080fd5b602083019150836001820283011115612f6557612f65600080fd5b9250929050565b60006001600160a01b03821661055b565b612ec881612f6c565b803561055b81612f7d565b60008060008060008060808789031215612fad57612fad600080fd5b863567ffffffffffffffff811115612fc757612fc7600080fd5b612fd389828a01612f1a565b96509650506020612fe689828a01612f86565b9450506040612ff789828a01612f86565b935050606087013567ffffffffffffffff81111561301757613017600080fd5b61302389828a01612f1a565b92509250509295509295509295565b80612f06565b6020810161055b8284613032565b60005b83811015613061578181015183820152602001613049565b83811115612ada5750506000910152565b600061307c825190565b808452602084019350613093818560208601613046565b601f01601f19169290920192915050565b60208082528101610b978184613072565b604081016130c38285613032565b610b976020830184613032565b80612ec8565b803561055b816130d0565b600080604083850312156130f7576130f7600080fd5b60006131038585612f86565b9250506020613114858286016130d6565b9150509250929050565b612f0681612f6c565b6020810161055b828461311e565b60008060006060848603121561314d5761314d600080fd5b60006131598686612f86565b935050602061316a86828701612f86565b925050604061317b868287016130d6565b9150509250925092565b80516040830190613196848261311e565b506020820151612ada6020850182613032565b6040810161055b8284613185565b60008060008060008060a087890312156131d3576131d3600080fd5b60006131df8989612f86565b96505060206131f089828a01612f86565b955050604061320189828a016130d6565b945050606061321289828a016130d6565b935050608087013567ffffffffffffffff81111561301757613017600080fd5b60ff8116612f06565b6020810161055b8284613232565b6000613255838361311e565b505060200190565b6000613267825190565b80845260209384019383018060005b8381101561329b57815161328a8882613249565b975060208301925050600101613276565b509495945050505050565b60208082528101610b97818461325d565b6000602082840312156132cc576132cc600080fd5b60006125338484612f86565b634e487b7160e01b600052604160045260246000fd5b601f19601f830116810181811067ffffffffffffffff82111715613314576133146132d8565b6040525050565b600061332660405190565b905061333282826132ee565b919050565b600067ffffffffffffffff821115613351576133516132d8565b601f19601f83011660200192915050565b82818337506000910152565b600061338161337c84613337565b61331b565b90508281526020810184848401111561339c5761339c600080fd5b6133a7848285613362565b509392505050565b600082601f8301126133c3576133c3600080fd5b813561253384826020860161336e565b600080600080608085870312156133ec576133ec600080fd5b60006133f88787612f86565b945050602061340987828801612f86565b935050604061341a87828801612f86565b925050606085013567ffffffffffffffff81111561343a5761343a600080fd5b613446878288016133af565b91505092959194509250565b62ffffff8116612f06565b6020810161055b8284613452565b60008060006060848603121561348357613483600080fd5b600061348f8686612f86565b93505060206134a0868287016130d6565b925050604061317b86828701612f86565b61ffff8116612f06565b6020810161055b82846134b1565b60ff8116612ec8565b803561055b816134c9565b600080600080600080600060e0888a0312156134fb576134fb600080fd5b60006135078a8a612f86565b97505060206135188a828b01612f86565b96505060406135298a828b016130d6565b955050606061353a8a828b016130d6565b945050608061354b8a828b016134d2565b93505060a061355c8a828b016130d6565b92505060c061356d8a828b016130d6565b91505092959891949750929550565b6000806040838503121561359257613592600080fd5b600061359e8585612f86565b925050602061311485828601612f86565b60006135bb8383613185565b505060400190565b60006135cd825190565b80845260209384019383018060005b8381101561329b5781516135f088826135af565b9750602083019250506001016135dc565b60208082528101610b9781846135c3565b634e487b7160e01b600052601160045260246000fd5b60008282101561363a5761363a613612565b500390565b600081600019048311821515161561365957613659613612565b500290565b6000821982111561367157613671613612565b500190565b634e487b7160e01b600052601260045260246000fd5b60008261369b5761369b613676565b500490565b80516000906102008401906136b5858261311e565b5060208301516136c8602086018261311e565b5060408301516136db6040860182613032565b5060608301516136ee6060860182613032565b5060808301516137016080860182613032565b5060a083015161371460a0860182613032565b5060c083015161372760c0860182613032565b5060e083015161373a60e0860182613032565b5061010083015161374f610100860182613032565b50610120830151613764610120860182613032565b50610140830151613779610140860182613032565b5061016083015161378e610160860182613032565b506101808301516137a3610180860182613032565b506101a08301516137b86101a0860182613032565b506101c08301516137cd6101c0860182613452565b506101e08301518482036101e086015261197d8282613072565b60208082528101610b9781846136a0565b606081016138068286613032565b6138136020830185613032565b6125336040830184613032565b634e487b7160e01b600052602260045260246000fd5b60028104600182168061384a57607f821691505b60208210810361385c5761385c613820565b50919050565b60008060006060848603121561387a5761387a600080fd5b60006138868686612f86565b935050602061389786828701612f86565b925050604061317b868287016134d2565b80516000906102008401906138bd858261311e565b5060208301516138d0602086018261311e565b5060408301516138e3604086018261311e565b5060608301516138f6606086018261311e565b5060808301516139096080860182613032565b5060a083015161391c60a0860182613032565b5060c083015161392f60c0860182613032565b5060e083015161394260e0860182613032565b50610100830151613957610100860182613032565b5061012083015161396c610120860182613032565b50610140830151613981610140860182613032565b50610160830151613996610160860182613032565b506101808301516139ab610180860182613032565b506101a08301516139c06101a0860182613452565b506101c08301516137cd6101c0860182613232565b60208082528101610b9781846138a8565b634e487b7160e01b600052603260045260246000fd5b600061055b613a088381565b90565b612f06816139fc565b60808101613a228287613032565b613a2f6020830186613a0b565b613a3c6040830185613a0b565b61197d6060830184613032565b60808101613a578287613a0b565b613a646020830186613032565b613a716040830185613032565b61197d6060830184613a0b565b80516000906101c0840190613a93858261311e565b506020830151613aa6602086018261311e565b506040830151613ab9604086018261311e565b506060830151613acc606086018261311e565b506080830151613adf6080860182613032565b5060a0830151613af260a0860182613032565b5060c0830151613b0560c0860182613032565b5060e0830151613b1860e0860182613032565b50610100830151613b2d610100860182613032565b50610120830151613b42610120860182613032565b50610140830151613b57610140860182613032565b50610160830151613b6c610160860182613452565b50610180830151613b81610180860182613232565b506101a08301518482036101a086015261197d8282613072565b60208082528101610b978184613a7e565b60a08101613bba828861311e565b613bc7602083018761311e565b613bd4604083018661311e565b613be1606083018561311e565b8181036080830152612cba8184613072565b62ffffff8116612ec8565b805161055b81613bf3565b600060208284031215613c1e57613c1e600080fd5b60006125338484613bfe565b60808101613c388287613032565b613c456020830186613232565b613a3c6040830185613032565b60008060408385031215613c6857613c68600080fd5b6000613c748585612f86565b9250506020613114858286016134d2565b8051600090610140840190613c9a858261311e565b506020830151613cad602086018261311e565b506040830151613cc06040860182613032565b506060830151613cd36060860182613032565b506080830151613ce66080860182613032565b5060a0830151613cf960a0860182613032565b5060c0830151613d0c60c0860182613032565b5060e0830151613d1f60e0860182613032565b50610100830151613d34610100860182613232565b5061012083015184820361012086015261197d8282613072565b60208082528101610b978184613c85565b6000613d69825190565b613d77818560208601613046565b9290920192915050565b6000610b978284613d5f565b6000613d9b61337c84613337565b905082815260208101848484011115613db657613db6600080fd5b6133a7848285613046565b600082601f830112613dd557613dd5600080fd5b8151612533848260208601613d8d565b600060208284031215613dfa57613dfa600080fd5b815167ffffffffffffffff811115613e1457613e14600080fd5b61253384828501613dc1565b6020808252810161055b81601f81527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00602082015260400190565b60408101613e69828561311e565b610b97602083018461311e565b805161055b816130d0565b600060208284031215613e9657613e96600080fd5b60006125338484613e76565b801515612ec8565b805161055b81613ea2565b600060208284031215613eca57613eca600080fd5b60006125338484613eaa565b805161055b81612f7d565b600060208284031215613ef657613ef6600080fd5b60006125338484613ed6565b600061ffff821661055b565b612f0681613f02565b60a08101613f258287613f0e565b613f32602083018661311e565b613f3f6040830185613032565b613f4c6060830184613032565b81810360808301526000815260208101610a10565b60608101613f6f828661311e565b613813602083018561311e565b60808101613f8a828761311e565b613f97602083018661311e565b613fa46040830185613032565b61197d6060830184613232565b60006000198203613fc457613fc4613612565b5060010190565b60c08101613fd98289613032565b613fe6602083018861311e565b613ff3604083018761311e565b6140006060830186613032565b61400d6080830185613032565b612cba60a0830184613032565b61190160f01b815260020160006140318285613032565b6020820191506140418284613032565b5060200192915050565b604081016140598285613032565b81810360208301526125338184613072565b6000815461407881613836565b60018216801561408f57600181146140a4576140d4565b60ff19831686528115158202860193506140d4565b60008581526020902060005b838110156140cc578154888201526001909101906020016140b0565b838801955050505b50505092915050565b6000610b97828461406b565b60a081016140f78288613a0b565b6141046020830187613032565b6141116040830186613a0b565b61411e6060830185613032565b610a10608083018461311e56feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212209d4df6080488c965e85c8d46a748d3e9c678e134194f5c0fad6ef2903c78217b64736f6c634300080f0033a26469706673582212204b619fda80c15b4e75b8d2761286fe37fd0165cae1297695220dd54ad6154e8764736f6c634300080f0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000608cb7c3168427091f5994a45baf12083964b4a3
-----Decoded View---------------
Arg [0] : _master (address): 0x608Cb7C3168427091F5994A45Baf12083964B4A3
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000608cb7c3168427091f5994a45baf12083964b4a3
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.