Overview
ETH Balance
ETH Value
$0.00Latest 25 from a total of 387 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Create Pool | 14163915 | 385 days ago | IN | 0 ETH | 0.00014264 | ||||
| Create Pool | 13862050 | 392 days ago | IN | 0 ETH | 0.00015084 | ||||
| Create Pool | 13559562 | 400 days ago | IN | 0 ETH | 0.00104057 | ||||
| Create Pool | 13449111 | 402 days ago | IN | 0 ETH | 0.00014143 | ||||
| Create Pool | 11877795 | 440 days ago | IN | 0 ETH | 0.00056158 | ||||
| Create Pool | 10331941 | 476 days ago | IN | 0 ETH | 0.00020526 | ||||
| Create Pool | 9928965 | 486 days ago | IN | 0 ETH | 0.00069699 | ||||
| Create Pool | 9928900 | 486 days ago | IN | 0 ETH | 0.00069699 | ||||
| Create Pool | 9928843 | 486 days ago | IN | 0 ETH | 0.00070122 | ||||
| Create Pool | 9928718 | 486 days ago | IN | 0 ETH | 0.00079359 | ||||
| Create Pool | 9928604 | 486 days ago | IN | 0 ETH | 0.00071438 | ||||
| Create Pool | 9928587 | 486 days ago | IN | 0 ETH | 0.00072303 | ||||
| Create Pool | 9927686 | 486 days ago | IN | 0 ETH | 0.00085323 | ||||
| Create Pool | 9927545 | 486 days ago | IN | 0 ETH | 0.00086353 | ||||
| Create Pool | 9927458 | 486 days ago | IN | 0 ETH | 0.00086353 | ||||
| Create Pool | 9927321 | 486 days ago | IN | 0 ETH | 0.00084347 | ||||
| Create Pool | 9927188 | 486 days ago | IN | 0 ETH | 0.00088332 | ||||
| Create Pool | 9927085 | 486 days ago | IN | 0 ETH | 0.00079856 | ||||
| Create Pool | 9927060 | 486 days ago | IN | 0 ETH | 0.00079758 | ||||
| Create Pool | 9927038 | 486 days ago | IN | 0 ETH | 0.00079758 | ||||
| Create Pool | 9926830 | 486 days ago | IN | 0 ETH | 0.00078647 | ||||
| Create Pool | 9926817 | 486 days ago | IN | 0 ETH | 0.00079117 | ||||
| Create Pool | 9926784 | 486 days ago | IN | 0 ETH | 0.00078647 | ||||
| Create Pool | 9926751 | 486 days ago | IN | 0 ETH | 0.00078263 | ||||
| Create Pool | 9926737 | 486 days ago | IN | 0 ETH | 0.00078235 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 28255767 | 6 hrs ago | 0 ETH | ||||
| 28254454 | 7 hrs ago | 0 ETH | ||||
| 28254454 | 7 hrs ago | 0 ETH | ||||
| 28252957 | 8 hrs ago | 0 ETH | ||||
| 28252156 | 9 hrs ago | 0 ETH | ||||
| 28248601 | 11 hrs ago | 0 ETH | ||||
| 28232938 | 21 hrs ago | 0 ETH | ||||
| 28232938 | 21 hrs ago | 0 ETH | ||||
| 28232938 | 21 hrs ago | 0 ETH | ||||
| 28228823 | 24 hrs ago | 0 ETH | ||||
| 28228823 | 24 hrs ago | 0 ETH | ||||
| 28221391 | 28 hrs ago | 0 ETH | ||||
| 28221196 | 28 hrs ago | 0 ETH | ||||
| 28220015 | 29 hrs ago | 0 ETH | ||||
| 28216497 | 31 hrs ago | 0 ETH | ||||
| 28216382 | 31 hrs ago | 0 ETH | ||||
| 28215930 | 32 hrs ago | 0 ETH | ||||
| 28215930 | 32 hrs ago | 0 ETH | ||||
| 28215930 | 32 hrs ago | 0 ETH | ||||
| 28214107 | 33 hrs ago | 0 ETH | ||||
| 28214107 | 33 hrs ago | 0 ETH | ||||
| 28214015 | 33 hrs ago | 0 ETH | ||||
| 28214015 | 33 hrs ago | 0 ETH | ||||
| 28214015 | 33 hrs ago | 0 ETH | ||||
| 28204287 | 38 hrs ago | 0 ETH |
Cross-Chain Transactions
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
Contract ABI
API[{"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
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.