Source Code
Overview
ETH Balance
ETH Value
$0.00Latest 7 from a total of 7 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Create Pool | 586199 | 439 days ago | IN | 0 ETH | 0.00071814 | ||||
| Create Pool | 138277 | 576 days ago | IN | 0 ETH | 0.00018451 | ||||
| Create Pool | 105420 | 585 days ago | IN | 0 ETH | 0.00366927 | ||||
| Create Pool | 105390 | 585 days ago | IN | 0 ETH | 0.00003841 | ||||
| Create Pool | 105389 | 585 days ago | IN | 0 ETH | 0.00003844 | ||||
| Create Pool | 105362 | 585 days ago | IN | 0 ETH | 0.00003852 | ||||
| Create Pool | 73443 | 595 days ago | IN | 0 ETH | 0.00003762 |
Latest 7 internal transactions
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 586199 | 439 days ago | Contract Creation | 0 ETH | |||
| 138277 | 576 days ago | Contract Creation | 0 ETH | |||
| 105420 | 585 days ago | Contract Creation | 0 ETH | |||
| 105390 | 585 days ago | Contract Creation | 0 ETH | |||
| 105389 | 585 days ago | Contract Creation | 0 ETH | |||
| 105362 | 585 days ago | Contract Creation | 0 ETH | |||
| 73443 | 595 days ago | Contract Creation | 0 ETH |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
RitsuStablePoolFactory
Compiler Version
v0.8.23+commit.f704f362
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0-or-later AND GPL-3.0-or-later AND MIT
// File contracts/interfaces/factory/IPoolFactory.sol
// Original license: 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);
}
// File contracts/interfaces/factory/IBasePoolFactory.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
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);
}
// File contracts/interfaces/master/IFeeManager.sol
// Original license: 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);
}
// File contracts/interfaces/master/IForwarderRegistry.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
interface IForwarderRegistry {
function isForwarder(address forwarder) external view returns (bool);
}
// File contracts/interfaces/master/IPoolMaster.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
/// @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 wETH() 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, address token0, address token1) external;
}
// File contracts/interfaces/pool/IPool.sol
// Original license: 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 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);
}
// File contracts/interfaces/token/IERC20Base.sol
// Original license: 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);
}
// File contracts/interfaces/token/IERC20.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
interface IERC20 is IERC20Base {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
// File contracts/interfaces/token/IERC20Permit.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
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);
}
// File contracts/interfaces/token/IERC20Permit2.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
interface IERC20Permit2 is IERC20Permit {
function permit2(address owner, address spender, uint amount, uint deadline, bytes calldata signature) external;
}
// File contracts/interfaces/pool/IBasePool.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
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
);
}
// File contracts/interfaces/pool/IBasePoolV2.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
interface IBasePoolV2 is IBasePool {
function poolVersion() external view returns (uint);
function sync() external;
event MintProtocolFee(
address indexed feeRecipient,
uint24 protocolFee,
uint liquidity,
uint totalSupply
);
event Swapped(
address indexed sender,
address indexed user,
address indexed tokenOut,
uint amountIn,
uint amountOut,
uint24 swapFee,
address to
);
event Fee(
uint amount0,
uint amount1
);
}
// File contracts/interfaces/vault/IERC3156FlashBorrower.sol
// Original license: 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);
}
// File contracts/interfaces/vault/IERC3156FlashLender.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
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);
}
// File contracts/interfaces/pool/IPoolFlashLoan.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
interface IPoolFlashLoan is IERC3156FlashLender {
/**
* @dev Emitted for each individual flash loan performed by `flashLoan`.
*/
event FlashLoan(address indexed recipient, address indexed token, uint amount, uint feeAmount);
}
// File contracts/interfaces/pool/IStablePoolV2.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
interface IStablePoolV2 is IBasePoolV2 {
function token0PrecisionMultiplier() external view returns (uint);
function token1PrecisionMultiplier() external view returns (uint);
/// @dev Returns the amplifier coefficient of the stable pool.
function getA() external view returns (uint64);
}
// File contracts/interfaces/token/IERC165.sol
// Original license: 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);
}
// File contracts/libraries/ECDSA.sol
// Original license: 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);
}
}
// File contracts/libraries/SignatureChecker.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
/**
* @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)
);
}
}
// File contracts/libraries/ERC20Permit2.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
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);
}
}
// File contracts/libraries/Math.sol
// Original license: 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 min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function sqrtInt(uint256 x) internal pure returns (uint256) {
if (x == 0) {
return 0;
}
uint z = (x + 1e18) / 2;
uint y = x;
for (uint i; i < 256; ) {
if (z == y) {
return y;
}
y = z;
z = (x * 1e18 / z + z) / 2;
unchecked {
++i;
}
}
revert();
}
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.
/// Reverts if x is zero.
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.
/// This allows x to be zero.
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.
/// Reverts if x is zero.
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.
/// Reverts if x is zero.
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)
}
}
}
function mulUnsafe(
uint256 x,
uint256 y
) internal pure returns (uint256 z) {
assembly {
// Store x * y in z for now.
z := mul(x, y)
}
}
// 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)
}
}
}
// File contracts/libraries/StableMath.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
library StableMath {
/// @notice Calculate the new balances of the tokens given the indexes of the token
/// that is swapped from (FROM) and the token that is swapped to (TO).
/// This function is used as a helper function to calculate how much TO token
/// the user should receive on swap.
/// @dev Originally https://github.com/saddle-finance/saddle-contract/blob/0b76f7fb519e34b878aa1d58cffc8d8dc0572c12/contracts/SwapUtils.sol#L432.
/// @param x The new total amount of FROM token.
/// @return y The amount of TO token that should remain in the pool.
function getY(uint a, uint x, uint d) internal pure returns (uint y) {
//uint c = (d * d) / (x * 2);
uint c = Math.mulDiv(d, d, Math.mulUnsafeFirst(2, x));
//c = (c * d) / 4000;
c = Math.mulDivUnsafeLast(c, d, Math.mulUnsafe(4, a));
//uint b = x + (d / 2000);
uint b = x + Math.divUnsafeLast(d, Math.mulUnsafe(2, a));
uint yPrev;
y = d;
/// @dev Iterative approximation.
for (uint i; i < 256; ) {
yPrev = y;
//y = (y * y + c) / (y * 2 + b - d);
y = (y * y + c) / (Math.mulUnsafeFirst(2, y) + b - d);
if (Math.within1(y, yPrev)) {
break;
}
unchecked {
++i;
}
}
}
// Overflow checks should be applied before calling this function.
// The maximum XPs are `3802571709128108338056982581425910818` under the A of 1,000.
function computeDFromAdjustedBalances(uint a, uint xp0, uint xp1) internal pure returns (uint d) {
uint s = xp0 + xp1;
if (s != 0) {
uint prevD;
d = s;
uint nA = Math.mulUnsafe(2, a);
uint nA_;
unchecked {
nA_ = nA - 1;
}
for (uint i; i < 256; ) {
//uint dP = (((d * d) / xp0) * d) / xp1 / 4;
uint dP = Math.divUnsafeLast(Math.mulDiv(Math.mulDiv(d, d, xp0), d, xp1), 4);
prevD = d;
//d = (((2000 * s) + 2 * dP) * d) / ((2000 - 1) * d + 3 * dP);
d = Math.mulDivUnsafeFirst(
// `s` cannot be zero and this value will never be zero.
Math.mulUnsafeFirst(nA, s) + Math.mulUnsafeFirst(2, dP),
d,
Math.mulUnsafeFirst(nA_, d) + Math.mulUnsafeFirst(3, dP)
);
if (Math.within1(d, prevD)) {
break;
}
unchecked {
++i;
}
}
}
}
}
// File contracts/pool/BasePoolFactory.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
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) {
}
}
// File contracts/interfaces/master/IFeeRecipient.sol
// Original license: 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;
}
// File contracts/libraries/ReentrancyGuard.sol
// Original license: 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 {
/// @dev Public to allow external contracts to read the status.
uint256 public reentrantStatus = 1;
/**
* @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() {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(reentrantStatus == 1);
// Any calls to nonReentrant after this point will fail
reentrantStatus = 2;
_;
reentrantStatus = 1;
}
}
// File contracts/libraries/TransferHelper.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
/// @dev The ETH transfer has failed.
error ETHTransferFailed();
/// @dev The ERC20 `transferFrom` has failed.
error TransferFromFailed();
/// @dev The ERC20 `transfer` has failed.
error TransferFailed();
/// @dev The ERC20 `approve` has failed.
error ApproveFailed();
/// @dev Helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true / false.
library TransferHelper {
function safeApprove(
address token,
address to,
uint value
) internal {
// bytes4(keccak256(bytes("approve(address,uint256)")));
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
if (!success || (data.length != 0 && !abi.decode(data, (bool)))) {
revert ApproveFailed();
}
}
function safeTransfer(
address token,
address to,
uint value
) internal {
// bytes4(keccak256(bytes("transfer(address,uint256)")));
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
if (!success || (data.length != 0 && !abi.decode(data, (bool)))) {
revert TransferFailed();
}
}
function safeTransferFrom(
address token,
address from,
address to,
uint value
) internal {
// bytes4(keccak256(bytes("transferFrom(address,address,uint256)")));
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
if (!success || (data.length != 0 && !abi.decode(data, (bool)))) {
revert TransferFromFailed();
}
}
function safeTransferETH(address to, uint value) internal {
// solhint-disable-next-line avoid-low-level-calls
(bool success, ) = to.call{value: value}("");
if (!success) {
revert ETHTransferFailed();
}
}
}
// File contracts/pool/PoolFlashLoans.sol
// Original license: SPDX_License_Identifier: GPL-3.0-or-later
pragma solidity ^0.8.0;
/**
* @dev Handles Flash Loans through the Pool.
*/
abstract contract PoolFlashLoans is IPoolFlashLoan, ReentrancyGuard {
uint private constant FLASH_LOAN_FEE = 5e15; // 0.5%
bytes32 private constant ERC3156_CALLBACK_SUCCESS = keccak256("ERC3156FlashBorrower.onFlashLoan");
/**
* @dev Returns the protocol fee amount to charge for a flash loan of `amount`.
*/
function _calculateFlashLoanFeeAmount(uint amount) private pure returns (uint) {
return amount * FLASH_LOAN_FEE / 1e18;
}
function _payFeeAmount(address token, uint amount) private {
if (amount != 0) {
address _feeRecipient = _getFeeRecipient();
if (_feeRecipient != address(0)) {
TransferHelper.safeTransfer(token, _feeRecipient, amount);
IFeeRecipient(_feeRecipient).notifyFees(10, token, amount, FLASH_LOAN_FEE, abi.encode(2));
}
}
}
function _getFeeRecipient() internal virtual view returns (address) {}
// EIP-3156 Implementations
/**
* @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 override returns (uint256) {
return IERC20(token).balanceOf(address(this));
}
/**
* @dev The fee to be charged for a given loan.
* @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 pure override returns (uint256) {
return _calculateFlashLoanFeeAmount(amount);
}
/**
* @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 userData Arbitrary data structure, intended to contain user-defined parameters.
*/
function flashLoan(
IERC3156FlashBorrower receiver,
address token,
uint amount,
bytes memory userData
) external override nonReentrant returns (bool) {
uint preLoanBalance = IERC20(token).balanceOf(address(this));
uint feeAmount = _calculateFlashLoanFeeAmount(amount);
require(preLoanBalance >= amount, "INSUFFICIENT_FLASH_LOAN_BALANCE");
TransferHelper.safeTransfer(token, address(receiver), amount);
require(
receiver.onFlashLoan(msg.sender, token, amount, feeAmount, userData) == ERC3156_CALLBACK_SUCCESS,
"IERC3156_CALLBACK_FAILED"
);
// Checking for loan repayment first (without accounting for fees) makes for simpler debugging, and results
// in more accurate revert reasons if the flash loan protocol fee percentage is zero.
uint postLoanBalance = IERC20(token).balanceOf(address(this));
require(postLoanBalance >= preLoanBalance, "INVALID_POST_LOAN_BALANCE");
// No need for checked arithmetic since we know the loan was fully repaid.
uint receivedFeeAmount = postLoanBalance - preLoanBalance;
require(receivedFeeAmount >= feeAmount, "INSUFFICIENT_FLASH_LOAN_FEE_AMOUNT");
_payFeeAmount(token, receivedFeeAmount);
emit FlashLoan(address(receiver), token, amount, receivedFeeAmount);
return true;
}
}
// File contracts/interfaces/ICallback.sol
// Original license: 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;
}
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;
}
function syncSwapBaseSwapCallback(BaseSwapCallbackParams calldata params) external;
}
// File contracts/interfaces/IOwnable.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
interface IOwnable {
function owner() external view returns (address);
}
// File contracts/interfaces/IWETH.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity >=0.5.0;
interface IWETH {
function deposit() external payable;
function transfer(address to, uint value) external returns (bool);
function transferFrom(address from, address to, uint value) external returns (bool);
function withdraw(uint) external;
}
// File contracts/libraries/MetadataHelper.sol
// Original license: 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, "");
}
}
}
// File contracts/pool/stable-delegate/RitsuStablePool.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
//import "../../libraries/ReentrancyGuard.sol";
error Overflow();
//error InsufficientLiquidityMinted();
contract RitsuStablePool is ERC20Permit2, PoolFlashLoans {
using Math for uint;
address private constant WETH = 0xA51894664A773981C6C112C43ce576f315d5b1B6; // Linea WETH
address public constant master = 0x12AF3Ec993EC5d5bD789b3e989c9E95A2F6c586D; // Linea V2 Pool Master
uint private constant MAX_FEE = 1e5; /// @dev 100%.
/// @dev Pool type `2` for stable pools.
uint16 public constant poolType = 2;
uint public constant poolVersion = 2;
address public immutable token0;
address public immutable token1;
/// @dev Multipliers for each pooled token's precision to get to the pool precision decimals
/// which is agnostic to the pool, but usually is 18.
/// For example, TBTC has 18 decimals, so the multiplier should be 10 ** (18 - 18) = 1.
/// WBTC has 8, so the multiplier should be 10 ** (18 - 8) => 10 ** 10.
/// The value is only for stable pools, and has no effects on non-stable pools.
uint public immutable token0PrecisionMultiplier;
uint public immutable token1PrecisionMultiplier;
/// @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.
uint128 private reserve0_;
uint128 private reserve1_;
function reserve0() external view returns (uint _reserve0) {
_reserve0 = reserve0_;
}
function reserve1() external view returns (uint _reserve1) {
_reserve1 = 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 invariantLast;
struct PoolParams {
uint64 initialA;
uint64 futureA;
uint64 initialTime;
uint64 futureTime;
}
PoolParams public poolParams;
struct TokenAmount {
address token;
uint amount;
}
/*
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
);
event MintProtocolFee(
address indexed feeRecipient,
uint24 protocolFee,
uint liquidity,
uint totalSupply
);
event Swapped(
address indexed sender,
address indexed user,
address indexed tokenOut,
uint amountIn,
uint amountOut,
uint24 swapFee,
address to
);
event Fee(
uint amount0,
uint amount1
);
receive() external payable {}
fallback() external payable {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Call the implementation.
// out and outsize are 0 because we don't know the size yet.
let result := delegatecall(
gas(),
0x60df1f3124128B29D3D595D91CD13dE0B84bD997,
0,
calldatasize(),
0,
0
)
// Copy the returned data.
returndatacopy(0, 0, returndatasize())
switch result
// delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
/// @dev Factory must ensures that the parameters are valid.
constructor() {
(bytes memory _deployData) = IPoolFactory(msg.sender).getDeployData();
(address _token0, address _token1, uint _token0PrecisionMultiplier, uint _token1PrecisionMultiplier) = abi.decode(
_deployData, (address, address, uint, uint)
);
//address _master = IPoolFactory(msg.sender).master();
//master = _master;
//wETH = IPoolMaster(_master).wETH();
(token0, token1, token0PrecisionMultiplier, token1PrecisionMultiplier) = (
_token0, _token1, _token0PrecisionMultiplier, _token1PrecisionMultiplier
);
poolParams = PoolParams(2000, 2000, 0, 0);
// 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("Ritsu Stable LP")),
string(abi.encodePacked(_symbol0, "/", _symbol1, "-S"))
);
} else {
_initialize("RLP", "RLP");
}
}
/// @dev Returns the verified sender address otherwise `address(0)`.
function _getVerifiedSender(address _sender) private view returns (address) {
if (_sender != msg.sender) {
// The sender from non-forwarder is invalid.
try IPoolMaster(master).isForwarder(msg.sender) returns (bool _isTrustedForwarder) {
return _isTrustedForwarder ? _sender : msg.sender;
} catch {
return msg.sender;
}
}
return msg.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 nonReentrant returns (uint) {
ICallback.BaseMintCallbackParams memory params;
(params.to) = abi.decode(_data, (address));
(params.reserve0, params.reserve1) = getReserves();
(params.balance0, params.balance1) = _balances();
uint _a = getA();
params.newInvariant = _computeInvariant(_a, 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.mulDivUnsafeLast(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;
emit Fee(params.fee0, params.fee1);
// Calculates old invariant (where unbalanced fee added to) and, mint protocol fee if any.
params.oldInvariant = _computeInvariant(_a, params.reserve0, params.reserve1);
bool _feeOn;
(_feeOn, params.totalSupply) = _mintProtocolFee(_a, 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 = Math.mulDivUnsafeFirst(params.totalSupply, params.newInvariant - params.oldInvariant, params.oldInvariant);
}
// Mints liquidity for recipient.
if (params.liquidity == 0) {
revert InsufficientLiquidityMinted();
}
_mint(params.to, params.liquidity);
// Updates reserves and last invariant with new balances.
_updateReserves(params.balance0, params.balance1);
if (_feeOn) {
invariantLast = params.newInvariant;
}
// Calls callback with data.
if (_callback != address(0)) {
// Fills additional values for callback params.
params.sender = _sender;
params.callbackData = _callbackData;
ICallback(_callback).syncSwapBaseMintCallback(params);
}
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 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)];
uint _a = getA();
// Mints protocol fee if any.
bool _feeOn;
(_feeOn, params.totalSupply) = _mintProtocolFee(_a, params.balance0, params.balance1, 0);
// Calculates amounts of pool tokens proportional to balances.
// require(params.liquidity != 0);
params.amount0 = Math.mulDivUnsafeFirstLast(params.liquidity, params.balance0, params.totalSupply);
params.amount1 = Math.mulDivUnsafeFirstLast(params.liquidity, params.balance1, params.totalSupply);
//require(_amount0 != 0 || _amount1 != 0);
// Burns liquidity.
_burn(address(this), params.liquidity);
// Updates balances.
/// @dev Cannot underflow because amounts are lesser figures derived from balances.
unchecked {
params.balance0 -= params.amount0;
params.balance1 -= params.amount1;
}
// Updates reserves and last invariant with up-to-date balances (after transfers).
_updateReserves(params.balance0, params.balance1);
if (_feeOn) {
invariantLast = _computeInvariant(_a, params.balance0, params.balance1);
}
// Transfers pool tokens.
_transferTokens(token0, params.to, params.amount0, params.withdrawMode);
_transferTokens(token1, params.to, params.amount1, params.withdrawMode);
// Calls callback with data.
if (_callback != address(0)) {
// Fills additional values for callback params.
params.sender = _getVerifiedSender(_sender);
params.callbackData = _callbackData;
ICallback(_callback).syncSwapBaseBurnCallback(params);
}
_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 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)];
uint _a = getA();
// Mints protocol fee if any.
bool _feeOn;
(_feeOn, params.totalSupply) = _mintProtocolFee(_a, params.balance0, params.balance1, 0);
// Calculates amounts of pool tokens proportional to balances.
require(params.liquidity != 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 withdraw 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(
_a,
params.swapFee, params.amount0, params.balance0 - params.amount0, params.balance1 - params.amount1, true
);
params.amount1 += params.amountSwapped;
params.amountOut = params.amount1;
params.amount0 = 0;
params.balance1 -= params.amount1;
emit Fee(params.feeIn, 0);
} else {
// Swaps `token1` for `token0`.
require(params.tokenOut == token0);
params.swapFee = _getSwapFee(_sender, token1, token0);
params.tokenIn = token1;
(params.amountSwapped, params.feeIn) = _getAmountOut(
_a,
params.swapFee, params.amount1, params.balance0 - params.amount0, params.balance1 - params.amount1, false
);
params.amount0 += params.amountSwapped;
params.amountOut = params.amount0;
params.amount1 = 0;
params.balance0 -= params.amount0;
emit Fee(0, params.feeIn);
}
require(params.amountOut != 0);
// Updates reserves and last invariant with up-to-date balances (updated above).
_updateReserves(params.balance0, params.balance1);
if (_feeOn) {
invariantLast = _computeInvariant(_a, params.balance0, params.balance1);
}
// 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;
ICallback(_callback).syncSwapBaseBurnSingleCallback(params);
}
_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 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) = getReserves();
(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(
getA(),
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);
emit Fee(params.feeIn, 0);
} 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(
getA(),
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);
emit Fee(0, params.feeIn);
}
require(params.amountIn != 0 && params.amountOut != 0);
// Updates reserves with up-to-date balances (updated above).
_updateReserves(params.balance0, params.balance1);
// 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;
ICallback(_callback).syncSwapBaseSwapCallback(params);
}
_tokenAmount.token = params.tokenOut;
_tokenAmount.amount = params.amountOut;
emit Swapped(
msg.sender,
_sender,
params.tokenOut,
params.amountIn,
params.amountOut,
params.swapFee,
params.to
);
}
function _getSwapFee(address _sender, address _tokenIn, address _tokenOut) private view returns (uint24 _swapFee) {
_swapFee = getSwapFee(_sender, _tokenIn, _tokenOut, abi.encode(msg.sender));
}
/// @dev This function doesn't check the forwarder.
function getSwapFee(address _sender, address _tokenIn, address _tokenOut, bytes memory data) public view returns (uint24) {
try IPoolMaster(master).getSwapFee(address(this), _sender, _tokenIn, _tokenOut, data) returns (uint24 _swapFee) {
return _swapFee;
} catch {
return 50; // 0.05%
}
}
function getProtocolFee() public view returns (uint24) {
try IPoolMaster(master).getProtocolFee(address(this)) returns (uint24 _protocolFee) {
return _protocolFee;
} catch {
return 30000; // 30%
}
}
function _updateReserves(uint _balance0, uint _balance1) private {
if (_balance0 > type(uint128).max) {
revert Overflow();
}
if (_balance1 > type(uint128).max) {
revert Overflow();
}
(reserve0_, reserve1_) = (uint128(_balance0), uint128(_balance1));
emit Sync(_balance0, _balance1);
}
function _transferTokens(address token, address to, uint amount, uint8 withdrawMode) private {
if (withdrawMode == 1 && token == WETH) {
IWETH(WETH).withdraw(amount);
TransferHelper.safeTransferETH(to, amount);
} else {
TransferHelper.safeTransfer(token, to, amount);
}
}
function _balances() private view returns (uint balance0, uint balance1) {
balance0 = IERC20(token0).balanceOf(address(this));
balance1 = IERC20(token1).balanceOf(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) {
if (_amount1 >= _amount1Optimal) {
unchecked {
_token1Fee = Math.mulDivUnsafeLast(_swapFee, _amount1 - _amount1Optimal, MAX_FEE);
}
} else {
uint _amount0Optimal = Math.mulDivUnsafeLast(_amount1, _reserve0, _reserve1);
_token0Fee = Math.mulDivUnsafeLast(_swapFee, _amount0 - _amount0Optimal, MAX_FEE);
}
}
}
function _getFeeRecipient() internal view override returns (address) {
try IPoolMaster(master).getFeeRecipient() returns (address _feeRecipient) {
return _feeRecipient;
} catch {
return address(0);
}
}
function _mintProtocolFee(uint _a, uint _reserve0, uint _reserve1, uint _invariant) private returns (bool _feeOn, uint _totalSupply) {
_totalSupply = totalSupply;
address _feeRecipient = _getFeeRecipient();
_feeOn = (_feeRecipient != address(0));
uint _invariantLast = invariantLast;
if (_invariantLast != 0) {
if (_feeOn) {
if (_invariant == 0) {
_invariant = _computeInvariant(_a, _reserve0, _reserve1);
}
if (_invariant > _invariantLast) {
/// @dev Mints `protocolFee` % of growth in liquidity (invariant).
uint24 _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.
try
IFeeRecipient(_feeRecipient).notifyFees(2, address(this), _liquidity, _protocolFee, abi.encode(2))
{} catch {}
_totalSupply += _liquidity; // update cached value.
emit MintProtocolFee(_feeRecipient, _protocolFee, _liquidity, _totalSupply);
}
}
} else {
/// @dev Resets last invariant to clear measured growth if protocol fee is not enabled.
invariantLast = 0;
}
}
}
function getReserves() public view returns (uint _reserve0, uint _reserve1) {
(_reserve0, _reserve1) = (reserve0_, reserve1_);
}
function _getAmountOut(
uint _a,
uint _swapFee,
uint _amountIn,
uint _reserve0,
uint _reserve1,
bool _token0In
) private view returns (uint _dy, uint _feeIn) {
if (_amountIn != 0) {
uint _adjustedReserve0 = Math.mulUnsafeFirst(token0PrecisionMultiplier, _reserve0);
uint _adjustedReserve1 = Math.mulUnsafeFirst(token1PrecisionMultiplier, _reserve1);
_feeIn = Math.mulDivUnsafeFirstLast(_amountIn, _swapFee, MAX_FEE);
uint _feeDeductedAmountIn = _amountIn - _feeIn;
uint _d = StableMath.computeDFromAdjustedBalances(_a, _adjustedReserve0, _adjustedReserve1);
if (_token0In) {
uint _x = _adjustedReserve0 + Math.mulUnsafeFirst(token0PrecisionMultiplier, _feeDeductedAmountIn);
uint _y = StableMath.getY(_a, _x, _d);
_dy = _adjustedReserve1 - _y - 1;
_dy = Math.divUnsafeLast(_dy, token1PrecisionMultiplier);
} else {
uint _x = _adjustedReserve1 + Math.mulUnsafeFirst(token1PrecisionMultiplier, _feeDeductedAmountIn);
uint _y = StableMath.getY(_a, _x, _d);
_dy = _adjustedReserve0 - _y - 1;
_dy = Math.divUnsafeLast(_dy, token0PrecisionMultiplier);
}
}
}
function _computeInvariant(uint _a, uint _reserve0, uint _reserve1) private view returns (uint _invariant) {
/// @dev Gets D, the StableSwap invariant, based on a set of balances and a particular A.
/// See the StableSwap paper for details.
/// Originally https://github.com/saddle-finance/saddle-contract/blob/0b76f7fb519e34b878aa1d58cffc8d8dc0572c12/contracts/SwapUtils.sol#L319.
/// Returns the invariant, at the precision of the pool.
uint _adjustedReserve0 = Math.mulUnsafeFirst(token0PrecisionMultiplier, _reserve0);
uint _adjustedReserve1 = Math.mulUnsafeFirst(token1PrecisionMultiplier, _reserve1);
_invariant = StableMath.computeDFromAdjustedBalances(_a, _adjustedReserve0, _adjustedReserve1);
}
function getA() public view returns (uint64) {
PoolParams memory params = poolParams;
// Ramps A.
if (uint64(block.timestamp) < params.futureTime) {
if (params.futureA < params.initialA) {
uint64 diff;
uint64 elapsed;
uint64 duration;
unchecked {
diff = params.initialA - params.futureA;
elapsed = uint64(block.timestamp) - params.initialTime;
duration = params.futureTime - params.initialTime;
}
return params.initialA - (diff * elapsed / duration);
}
}
return params.futureA;
}
}
// File contracts/pool/stable-delegate/RitsuStablePoolFactory.sol
// Original license: SPDX_License_Identifier: AGPL-3.0-or-later
pragma solidity ^0.8.0;
contract RitsuStablePoolFactory is BasePoolFactory {
constructor(address _master) BasePoolFactory(_master) {
}
function _createPool(address token0, address token1) internal override returns (address pool) {
// Tokens with decimals more than 18 are not supported and will lead to reverts.
uint token0PrecisionMultiplier = 10 ** (18 - IERC20(token0).decimals());
uint token1PrecisionMultiplier = 10 ** (18 - IERC20(token1).decimals());
bytes memory deployData = abi.encode(token0, token1, token0PrecisionMultiplier, token1PrecisionMultiplier);
cachedDeployData = deployData;
// Remove precision multipliers from salt and config.
deployData = abi.encode(token0, token1);
bytes32 salt = keccak256(deployData);
pool = address(new RitsuStablePool{salt: salt}()); // this will prevent duplicated pools.
// Register the pool with config.
IPoolMaster(master).registerPool(pool, 2, deployData, token0, token1);
}
}{
"viaIR": false,
"optimizer": {
"enabled": true,
"runs": 200,
"details": {
"yul": false
}
},
"evmVersion": "paris",
"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
60a060405234801561001057600080fd5b50604051620057e1380380620057e183398101604081905261003191610077565b6001600160a01b03166080526100a0565b60006001600160a01b0382165b92915050565b61005e81610042565b811461006957600080fd5b50565b805161004f81610055565b60006020828403121561008c5761008c600080fd5b6000610098848461006c565b949350505050565b608051615717620000ca6000396000818161010b0152818161027e015261056501526157176000f3fe60806040523480156200001157600080fd5b50600436106200005e5760003560e01c806313b8683f14620000635780634625a94d1462000092578063531aa03e14620000b8578063d039f62214620000ec578063ee97f7f31462000105575b600080fd5b6200007a6200007436600462000649565b6200012d565b604051620000899190620006bb565b60405180910390f35b620000a9620000a3366004620006f2565b62000264565b604051620000899190620007a2565b6200007a620000c9366004620007b2565b60006020818152928152604080822090935290815220546001600160a01b031681565b620000f66200030e565b60405162000089919062000852565b6200007a7f000000000000000000000000000000000000000000000000000000000000000081565b600080806200013f84860186620007b2565b91509150806001600160a01b0316826001600160a01b03160362000176576040516333910aef60e11b815260040160405180910390fd5b816001600160a01b0316816001600160a01b031610156200019357905b6001600160a01b038216620001bb576040516333910aef60e11b815260040160405180910390fd5b620001c78282620003a8565b6001600160a01b0380841660008181526020818152604080832087861680855290835281842080549688166001600160a01b03199788168117909155848452828520868652909352928190208054909516909117909355915192955090917f9c5d829b9b23efc461f9aeef91979ec04bb903feb3bee4f26d22114abfc7335b9062000254908790620006bb565b60405180910390a3505092915050565b604051634625a94d60e01b81526000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690634625a94d90620002bf908a908a908a908a908a908a906004016200089e565b602060405180830381865afa158015620002dd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000303919062000915565b979650505050505050565b6060600180546200031f9062000958565b80601f01602080910402602001604051908101604052809291908181526020018280546200034d9062000958565b80156200039e5780601f1062000372576101008083540402835291602001916200039e565b820191906000526020600020905b8154815290600101906020018083116200038057829003601f168201915b5050505050905090565b600080836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003ea573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041091906200099f565b6200041d906012620009da565b6200042a90600a62000b28565b90506000836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200046d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200049391906200099f565b620004a0906012620009da565b620004ad90600a62000b28565b9050600085858484604051602001620004ca949392919062000b46565b60408051601f1981840301815291905290506001620004ea828262000c54565b5085856040516020016200050092919062000d25565b60408051601f1981840301815290829052805160208201209092509081906200052990620005e3565b8190604051809103906000f59050801580156200054a573d6000803e3d6000fd5b5060405163a5a7f8b760e01b81529095506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a5a7f8b790620005a590889060029087908d908d9060040162000d5c565b600060405180830381600087803b158015620005c057600080fd5b505af1158015620005d5573d6000803e3d6000fd5b505050505050505092915050565b6149288062000dba83390190565b60008083601f840112620006085762000608600080fd5b50813567ffffffffffffffff811115620006255762000625600080fd5b602083019150836001820283011115620006425762000642600080fd5b9250929050565b60008060208385031215620006615762000661600080fd5b823567ffffffffffffffff8111156200067d576200067d600080fd5b6200068b85828601620005f1565b92509250509250929050565b60006001600160a01b0382165b92915050565b620006b58162000697565b82525050565b60208101620006a48284620006aa565b620006d68162000697565b8114620006e257600080fd5b50565b8035620006a481620006cb565b60008060008060008060a08789031215620007105762000710600080fd5b60006200071e8989620006e5565b96505060206200073189828a01620006e5565b95505060406200074489828a01620006e5565b94505060606200075789828a01620006e5565b935050608087013567ffffffffffffffff811115620007795762000779600080fd5b6200078789828a01620005f1565b92509250509295509295509295565b62ffffff8116620006b5565b60208101620006a4828462000796565b60008060408385031215620007ca57620007ca600080fd5b6000620007d88585620006e5565b9250506020620007eb85828601620006e5565b9150509250929050565b60005b8381101562000812578181015183820152602001620007f8565b50506000910152565b600062000826825190565b8084526020840193506200083f818560208601620007f5565b601f19601f8201165b9093019392505050565b602080825281016200086581846200081b565b9392505050565b82818337506000910152565b8183526000602084019350620008908385846200086c565b601f19601f84011662000848565b60a08101620008ae8289620006aa565b620008bd6020830188620006aa565b620008cc6040830187620006aa565b620008db6060830186620006aa565b8181036080830152620008f081848662000878565b98975050505050505050565b62ffffff8116620006d6565b8051620006a481620008fc565b6000602082840312156200092c576200092c600080fd5b60006200093a848462000908565b949350505050565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806200096d57607f821691505b60208210810362000982576200098262000942565b50919050565b60ff8116620006d6565b8051620006a48162000988565b600060208284031215620009b657620009b6600080fd5b60006200093a848462000992565b634e487b7160e01b600052601160045260246000fd5b60ff918216919081169082820390811115620006a457620006a4620009c4565b80825b600185111562000a405780860481111562000a1c5762000a1c620009c4565b600185161562000a2b57908102905b800262000a388560011c90565b9450620009fd565b94509492505050565b60008262000a5a5750600162000865565b8162000a695750600062000865565b816001811462000a82576002811462000a8d5762000ac1565b600191505062000865565b60ff84111562000aa15762000aa1620009c4565b8360020a91508482111562000aba5762000aba620009c4565b5062000865565b5060208310610133831016604e8410600b841016171562000af9575081810a8381111562000af35762000af3620009c4565b62000865565b62000b088484846001620009fa565b9250905081840481111562000b215762000b21620009c4565b0292915050565b600060ff8316925062000865600019848462000a49565b80620006b5565b6080810162000b568287620006aa565b62000b656020830186620006aa565b62000b74604083018562000b3f565b62000b83606083018462000b3f565b95945050505050565b634e487b7160e01b600052604160045260246000fd5b6000620006a462000bb08381565b90565b62000bbe8362000ba2565b815460001960089490940293841b1916921b91909117905550565b600062000be881848462000bb3565b505050565b8181101562000c0c5762000c0360008262000bd9565b60010162000bed565b5050565b601f82111562000be8576000818152602090206020601f8501048101602085101562000c395750805b62000c4d6020601f86010483018262000bed565b5050505050565b815167ffffffffffffffff81111562000c715762000c7162000b8c565b62000c7d825462000958565b62000c8a82828562000c10565b6020601f83116001811462000cc1576000841562000ca85750858201515b600019600886021c198116600286021786555062000d1d565b600085815260208120601f198616915b8281101562000cf3578885015182556020948501946001909201910162000cd1565b8683101562000d105784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b6040810162000d358285620006aa565b620008656020830184620006aa565b600061ffff8216620006a4565b620006b58162000d44565b60a0810162000d6c8288620006aa565b62000d7b602083018762000d51565b818103604083015262000d8f81866200081b565b905062000da06060830185620006aa565b62000daf6080830184620006aa565b969550505050505056fe610120604052601260805260016008553480156200001c57600080fd5b506000336001600160a01b031663d039f6226040518163ffffffff1660e01b8152600401600060405180830381865afa1580156200005e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620000889190810190620004a7565b905060008060008084806020019051810190620000a6919062000535565b61010081905260e08290526001600160a01b0380841660c052841660a052604080516080810182526107d0808252602082015260009181018290526060018190526907d000000000000007d0600b5593975091955093509150806200010b86620001df565b90925090506000806200011e87620001df565b915091508380156200012d5750815b156200018857620001826040516020016200014890620005a3565b60405160208183030381529060405284836040516020016200016c929190620005e9565b60408051601f19818403018152919052620002b7565b620001d0565b620001d0604051806040016040528060038152602001620524c560ec1b815250604051806040016040528060038152602001620524c560ec1b815250620002b760201b60201c565b50505050505050505062000901565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b1790529051600091606091839182916001600160a01b03871691620002299162000623565b600060405180830381855afa9150503d806000811462000266576040519150601f19603f3d011682016040523d82523d6000602084013e6200026b565b606091505b509150915081156200029a576001818060200190518101906200028f9190620004a7565b935093505050915091565b600060405180602001604052806000815250935093505050915091565b6004620002c5838262000730565b506005620002d4828262000730565b5046600655620002e3620002ea565b6007555050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60046040516200031e91906200087a565b6040519081900381206200035c92917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69046903090602001620008ab565b60405160208183030381529060405280519060200120905090565b634e487b7160e01b600052604160045260246000fd5b601f19601f83011681018181106001600160401b0382111715620003b557620003b562000377565b6040525050565b6000620003c860405190565b9050620003d682826200038d565b919050565b60006001600160401b03821115620003f757620003f762000377565b601f19601f83011660200192915050565b60005b83811015620004255781810151838201526020016200040b565b50506000910152565b6000620004456200043f84620003db565b620003bc565b905082815260208101848484011115620004625762000462600080fd5b6200046f84828562000408565b509392505050565b600082601f8301126200048d576200048d600080fd5b81516200049f8482602086016200042e565b949350505050565b600060208284031215620004be57620004be600080fd5b81516001600160401b03811115620004d957620004d9600080fd5b6200049f8482850162000477565b60006001600160a01b0382165b92915050565b6200050581620004e7565b81146200051157600080fd5b50565b8051620004f481620004fa565b8062000505565b8051620004f48162000521565b60008060008060808587031215620005505762000550600080fd5b60006200055e878762000514565b9450506020620005718782880162000514565b9350506040620005848782880162000528565b9250506060620005978782880162000528565b91505092959194509250565b6e0526974737520537461626c65204c5608c1b81526000600f8201620004f4565b6000620005cf825190565b620005df81856020860162000408565b9290920192915050565b6000620005f78285620005c4565b602f60f81b815260010191506200060f8284620005c4565b612d5360f01b81529150600282016200049f565b6000620006318284620005c4565b9392505050565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806200066357607f821691505b60208210810362000678576200067862000638565b50919050565b6000620004f46200068c8381565b90565b6200069a836200067e565b815460001960089490940293841b1916921b91909117905550565b6000620006c48184846200068f565b505050565b81811015620006e857620006df600082620006b5565b600101620006c9565b5050565b601f821115620006c4576000818152602090206020601f85010481016020851015620007155750805b620007296020601f860104830182620006c9565b5050505050565b81516001600160401b038111156200074c576200074c62000377565b6200075882546200064e565b62000765828285620006ec565b6020601f8311600181146200079c5760008415620007835750858201515b600019600886021c1981166002860217865550620007f8565b600085815260208120601f198616915b82811015620007ce5788850151825560209485019460019092019101620007ac565b86831015620007eb5784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b600081546200080f816200064e565b6001821680156200082957600181146200083f5762000871565b60ff198316865281151582028601935062000871565b60008581526020902060005b8381101562000869578154888201526001909101906020016200084b565b838801955050505b50505092915050565b600062000631828462000800565b62000893816200067e565b82525050565b8062000893565b6200089381620004e7565b60a08101620008bb828862000888565b620008ca602083018762000899565b620008d9604083018662000888565b620008e8606083018562000899565b620008f76080830184620008a0565b9695505050505050565b60805160a05160c05160e05161010051613f2c620009fc600039600081816104af01528181612240015281816122f90152818161232b01526124a801526000818161065b01528181612212015281816122a101528181612383015261247a01526000818161068f01528181610b4101528181610ba301528181610d0401528181610d60015281816115640152818161159d015281816116c2015281816117080152611e8301526000818161032801528181610b8201528181610bde01528181610cbe01528181610d25015281816115020152818161154301528181611729015281816117620152611dde0152600061043b0152613f2c6000f3fe6080604052600436106102085760003560e01c8063613255ab11610118578063baa8c7cb116100a0578063d6ea073d1161006f578063d6ea073d146106f3578063d9d98ce414610709578063da81573114610729578063dd62ed3e1461073e578063ee97f7f3146107765761020f565b8063baa8c7cb14610649578063d21220a71461067d578063d46300fd146106b1578063d505accf146106d35761020f565b80638b4c5470116100e75780638b4c5470146105b057806395d89b41146105dd578063a5a41031146105f2578063a9059cbb14610607578063b1dd61b6146106275761020f565b8063613255ab1461051657806370a08231146105365780637132bb7f146105635780637ecebe00146105835761020f565b806323b872dd1161019b5780633644e5151161016a5780633644e5151461046a578063443cb4bc1461047f5780634e25dc471461049d5780635a76f25e146104d15780635cffe9de146104f65761020f565b806323b872dd146103bc57806327b0bcea146103dc5780632c0198cc14610409578063313ce567146104295761020f565b8063095ea7b3116101d7578063095ea7b3146102f65780630dfe16811461031657806318160ddd1461035757806319706b381461036d5761020f565b806301ffc9a71461024957806306fdde031461027f57806307f293f7146102a15780630902f1ac146102c45761020f565b3661020f57005b36600080376000803660007360df1f3124128b29d3d595d91cd13de0b84bd9975af43d6000803e808015610242573d6000f35b3d6000fd5b005b34801561025557600080fd5b50610269610264366004612e13565b61079e565b6040516102769190612e3e565b60405180910390f35b34801561028b57600080fd5b506102946107f0565b6040516102769190612ea2565b3480156102ad57600080fd5b506102b7600a5481565b6040516102769190612eb9565b3480156102d057600080fd5b506009546001600160801b0380821691600160801b900416604051610276929190612ec7565b34801561030257600080fd5b50610269610311366004612f18565b61087e565b34801561032257600080fd5b5061034a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516102769190612f5e565b34801561036357600080fd5b506102b760005481565b34801561037957600080fd5b50600b546103ac906001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b6040516102769493929190612f7b565b3480156103c857600080fd5b506102696103d7366004612fb9565b610894565b3480156103e857600080fd5b506103fc6103f736600461305a565b610974565b604051610276919061311d565b34801561041557600080fd5b5061024761042436600461312b565b610ff1565b34801561043557600080fd5b5061045d7f000000000000000000000000000000000000000000000000000000000000000081565b60405161027691906131ae565b34801561047657600080fd5b506102b7611096565b34801561048b57600080fd5b506009546001600160801b03166102b7565b3480156104a957600080fd5b506102b77f000000000000000000000000000000000000000000000000000000000000000081565b3480156104dd57600080fd5b50600954600160801b90046001600160801b03166102b7565b34801561050257600080fd5b506102696105113660046132c7565b6110b5565b34801561052257600080fd5b506102b7610531366004613345565b611360565b34801561054257600080fd5b506102b7610551366004613345565b60016020526000908152604090205481565b34801561056f57600080fd5b506103fc61057e36600461305a565b6113d0565b34801561058f57600080fd5b506102b761059e366004613345565b60036020526000908152604090205481565b3480156105bc57600080fd5b506105d06105cb366004613366565b611a15565b60405161027691906133b8565b3480156105e957600080fd5b50610294611aa7565b3480156105fe57600080fd5b506105d0611ab4565b34801561061357600080fd5b50610269610622366004612f18565b611b37565b34801561063357600080fd5b5061063c600281565b60405161027691906133d0565b34801561065557600080fd5b506102b77f000000000000000000000000000000000000000000000000000000000000000081565b34801561068957600080fd5b5061034a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106bd57600080fd5b506106c6611bac565b60405161027691906133de565b3480156106df57600080fd5b506102476106ee366004613400565b611c71565b3480156106ff57600080fd5b506102b760085481565b34801561071557600080fd5b506102b7610724366004612f18565b611d66565b34801561073557600080fd5b506102b7600281565b34801561074a57600080fd5b506102b761075936600461349f565b600260209081526000928352604080842090915290825290205481565b34801561078257600080fd5b5061034a7312af3ec993ec5d5bd789b3e989c9e95a2f6c586d81565b60006001600160e01b031982166301ffc9a760e01b14806107cf57506001600160e01b0319821663d505accf60e01b145b806107ea57506001600160e01b03198216630b00663360e21b145b92915050565b600480546107fd906134e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610829906134e8565b80156108765780601f1061084b57610100808354040283529160200191610876565b820191906000526020600020905b81548152906001019060200180831161085957829003601f168201915b505050505081565b600061088b338484611d71565b50600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146108f0576108cb838261352a565b6001600160a01b03861660009081526002602090815260408083203384529091529020555b6001600160a01b0385166000908152600160205260408120805485929061091890849061352a565b90915550506001600160a01b0380851660008181526001602052604090819020805487019055519091871690600080516020613ed78339815191529061095f908790612eb9565b60405180910390a360019150505b9392505050565b604080518082019091526000808252602082015260085460011461099757600080fd5b6002600881905550610a4b60405180610200016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b610a578789018961353d565b60ff166101c08401526001600160a01b039081166020840152166060820152610a7e611dd9565b60a083015260808201523060009081526001602052604081205460c0830152610aa5611bac565b6001600160401b031690506000610ac78284608001518560a001516000611eff565b60e085015260c0840151909150600003610ae057600080fd5b610b0183608001518460c00151610af79190613583565b8460e00151900490565b61010084015260a083015160c0840151610b1e91610af791613583565b61012084015260c0830151610b349030906120c4565b610b3d8861212f565b97507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031683606001516001600160a01b031603610cbc57610bc7887f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006121d5565b62ffffff166101a084018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408501526101008401516080850151610c3d9285929091610c2190829061352a565b8761012001518860a00151610c36919061352a565b6001612202565b610180850152610160840181905261012084018051610c5d9083906135a2565b9052506101208301516101408401819052600061010085015260a084018051610c8790839061352a565b905250610180830151604051600080516020613eb783398151915291610caf916000906135cd565b60405180910390a1610e42565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031683606001516001600160a01b031614610cfe57600080fd5b610d49887f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006121d5565b62ffffff166101a084018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408501526101208401516101008501516080860151610dc693869390929091610daa919061352a565b8761012001518860a00151610dbf919061352a565b6000612202565b610180850152610160840181905261010084018051610de69083906135a2565b90525061010083015161014084018190526000610120850152608084018051610e1090839061352a565b905250610180830151604051600080516020613eb783398151915291610e3991600091906135e8565b60405180910390a15b826101400151600003610e5457600080fd5b610e6683608001518460a001516123b9565b8015610e8357610e7f8284608001518560a00151612472565b600a555b610ea183606001518460200151856101400151866101c001516124e4565b6001600160a01b03871615610f55576001600160a01b0388168352604080516020601f88018190048102820181019092528681529087908790819084018382808284376000920191909152505050506101e0840152604051630eace54160e11b81526001600160a01b03881690631d59ca8290610f2290869060040161373d565b600060405180830381600087803b158015610f3c57600080fd5b505af1158015610f50573d6000803e3d6000fd5b505050505b604051806040016040528084606001516001600160a01b03168152602001846101400151815250935082602001516001600160a01b0316336001600160a01b03167fd175a80c109434bb89948928ab2475a6647c94244cb70002197896423c8833638561010001518661012001518760c00151604051610fd79392919061374e565b60405180910390a350506001600855509695505050505050565b828042111561101357604051630407b05b60e31b815260040160405180910390fd5b6000611021888888886125a1565b9050611064888286868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061265a92505050565b61108157604051638baa579f60e01b815260040160405180910390fd5b61108c888888611d71565b5050505050505050565b600060065446146110ae576110a9612786565b905090565b5060075490565b60006008546001146110c657600080fd5b60026008556040516370a0823160e01b81526000906001600160a01b038616906370a08231906110fa903090600401612f5e565b602060405180830381865afa158015611117573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113b9190613781565b905060006111488561280f565b9050848210156111735760405162461bcd60e51b815260040161116a906137d9565b60405180910390fd5b61117e868887612835565b6040516323e30c8b60e01b81527f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9906001600160a01b038916906323e30c8b906111d49033908b908b9088908c906004016137e9565b6020604051808303816000875af11580156111f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112179190613781565b146112345760405162461bcd60e51b815260040161116a90613864565b6040516370a0823160e01b81526000906001600160a01b038816906370a0823190611263903090600401612f5e565b602060405180830381865afa158015611280573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a49190613781565b9050828110156112c65760405162461bcd60e51b815260040161116a906138a8565b60006112d2848361352a565b9050828110156112f45760405162461bcd60e51b815260040161116a906138b8565b6112fe8882612928565b876001600160a01b0316896001600160a01b03167f0d7d75e01ab95780d3cd1c8ec0dd6c2ce19e3a20427eec8bf53283b6fb8e95f08984604051611343929190612ec7565b60405180910390a360019450505050506001600855949350505050565b6040516370a0823160e01b81526000906001600160a01b038316906370a082319061138f903090600401612f5e565b602060405180830381865afa1580156113ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ea9190613781565b60408051808201909152600080825260208201526008546001146113f357600080fd5b6002600881905550611499604051806101c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b6114a58789018961353d565b60ff166101808401526001600160a01b0390811660208401521660408201526009546001600160801b03600160801b8204811660a08401521660808201526114eb611dd9565b60e083015260c08201526114fe8661212f565b95507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681604001516001600160a01b0316036116c057611588867f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006121d5565b62ffffff166101608201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166060820152608081015160c08201516115d6919061352a565b6101008201526116126115e7611bac565b6001600160401b031682610160015162ffffff1683610100015184608001518560a001516001612202565b610140830152610120820181905260e08201805161163190839061352a565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822926116869260009182916138fe565b60405180910390a3600080516020613eb783398151915281610140015160006040516116b39291906135cd565b60405180910390a1611883565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681604001516001600160a01b03161461170257600080fd5b61174d867f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006121d5565b62ffffff166101608201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016606082015260a081015160e082015161179b919061352a565b6101008201526117d76117ac611bac565b6001600160401b031682610160015162ffffff1683610100015184608001518560a001516000612202565b610140830152610120820181905260c0820180516117f690839061352a565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229261184d9260009291908390613933565b60405180910390a3600080516020613eb7833981519152600082610140015160405161187a9291906135e8565b60405180910390a15b6101008101511580159061189b575061012081015115155b6118a457600080fd5b6118b68160c001518260e001516123b9565b6118d4816060015182602001518361012001518461018001516124e4565b6001600160a01b03851615611988576001600160a01b0386168152604080516020601f86018190048102820181019092528481529085908590819084018382808284376000920191909152505050506101a082015260405163608dbcbb60e01b81526001600160a01b0386169063608dbcbb90611955908490600401613a85565b600060405180830381600087803b15801561196f57600080fd5b505af1158015611983573d6000803e3d6000fd5b505050505b6060810180516001600160a01b03908116845261012083018051602080870191909152925161010085015191516101608601519486015160405192851695948c169433947faa077b6dc26efdfd606d4340c04a5a222ff968ec199f0b184f4c0f7a5c8e8d71946119fd94919391929190613a96565b60405180910390a45060016008559695505050505050565b604051634625a94d60e01b81526000907312af3ec993ec5d5bd789b3e989c9e95a2f6c586d90634625a94d90611a579030908990899089908990600401613acb565b602060405180830381865afa925050508015611a90575060408051601f3d908101601f19168201909252611a8d91810190613b16565b60015b611a9c57506032611a9f565b90505b949350505050565b600580546107fd906134e8565b6040516302a64b8360e21b81526000907312af3ec993ec5d5bd789b3e989c9e95a2f6c586d90630a992e0c90611aee903090600401612f5e565b602060405180830381865afa925050508015611b27575060408051601f3d908101601f19168201909252611b2491810190613b16565b60015b611b32575061753090565b919050565b33600090815260016020526040812080548391908390611b5890849061352a565b90915550506001600160a01b03831660008181526001602052604090819020805485019055513390600080516020613ed783398151915290611b9b908690612eb9565b60405180910390a350600192915050565b60408051608081018252600b546001600160401b038082168352600160401b820481166020840152600160801b8204811693830193909352600160c01b900482166060820181905260009242161015611c685780600001516001600160401b031681602001516001600160401b03161015611c6857602081015181516040830151606084015192909103914282900391900380611c498385613b37565b611c539190613b73565b8451611c5f9190613ba0565b94505050505090565b60200151919050565b8380421115611c9357604051630407b05b60e31b815260040160405180910390fd5b6000611ca1898989896125a1565b9050600060018287878760405160008152602001604052604051611cc89493929190613bc3565b6020604051602081039080840390855afa158015611cea573d6000803e3d6000fd5b505050602060405103519050896001600160a01b0316816001600160a01b031614611d2857604051638baa579f60e01b815260040160405180910390fd5b6001600160a01b038116611d4f57604051638baa579f60e01b815260040160405180910390fd5b611d5a8a8a8a611d71565b50505050505050505050565b600061096d8261280f565b6001600160a01b0380841660008181526002602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590611dcc908590612eb9565b60405180910390a3505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611e289190612f5e565b602060405180830381865afa158015611e45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e699190613781565b6040516370a0823160e01b81529092506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190611eb8903090600401612f5e565b602060405180830381865afa158015611ed5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef99190613781565b90509091565b6000805481611f0c6129e9565b600a546001600160a01b0382161515945090915080156120b95783156120b35784600003611f4257611f3f888888612472565b94505b808511156120ae576000611f54611ab4565b9050600062ffffff8216611f68848961352a565b611f729087613583565b611f7c9190613583565b90506000611f8f8462ffffff8516613583565b88611fa262ffffff8616620186a061352a565b611fac9190613583565b611fb691906135a2565b90506000611fc48284613beb565b905080156120a957611fd68682612a63565b856001600160a01b031663843e821860023084886002604051602001611ffc9190613c07565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161202b959493929190613c44565b600060405180830381600087803b15801561204557600080fd5b505af1925050508015612056575060015b5061206181886135a2565b9650856001600160a01b03167f422815a3c1bfb8dd07ed3e682f42d4d640425d52f0b08da06718c8a2932e280285838a6040516120a093929190613c79565b60405180910390a25b505050505b6120b9565b6000600a555b505094509492505050565b6001600160a01b038216600090815260016020526040812080548392906120ec90849061352a565b90915550506000805482900381556040516001600160a01b03841690600080516020613ed783398151915290612123908590612eb9565b60405180910390a35050565b60006001600160a01b03821633146121ce57604051632af3bd5560e21b81527312af3ec993ec5d5bd789b3e989c9e95a2f6c586d9063abcef55490612178903390600401612f5e565b602060405180830381865afa9250505080156121b1575060408051601f3d908101601f191682019092526121ae91810190613c9a565b60015b6121bc575033919050565b806121c7573361096d565b5090919050565b5033919050565b6000611a9f848484336040516020016121ee9190612f5e565b604051602081830303815290604052611a15565b60008085156123ae5760006122377f000000000000000000000000000000000000000000000000000000000000000087612ab4565b905060006122657f000000000000000000000000000000000000000000000000000000000000000087612ab4565b9050612275888a620186a0612ac5565b92506000612283848a61352a565b905060006122928c8585612add565b905086156123245760006122c67f000000000000000000000000000000000000000000000000000000000000000084612ab4565b6122d090866135a2565b905060006122df8e8385612ba6565b905060016122ed828761352a565b6122f7919061352a565b7f0000000000000000000000000000000000000000000000000000000000000000900497506123a9915050565b60006123507f000000000000000000000000000000000000000000000000000000000000000084612ab4565b61235a90856135a2565b905060006123698e8385612ba6565b90506001612377828861352a565b612381919061352a565b7f00000000000000000000000000000000000000000000000000000000000000009004975050505b505050505b965096945050505050565b6001600160801b038211156123e157604051631a93c68960e11b815260040160405180910390fd5b6001600160801b0381111561240957604051631a93c68960e11b815260040160405180910390fd5b6001600160801b03808316908216600160801b026fffffffffffffffffffffffffffffffff1916176009556040517fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a906124669084908490612ec7565b60405180910390a15050565b60008061249f7f000000000000000000000000000000000000000000000000000000000000000085612ab4565b905060006124cd7f000000000000000000000000000000000000000000000000000000000000000085612ab4565b90506124da868383612add565b9695505050505050565b8060ff16600114801561251357506001600160a01b03841673a51894664a773981c6c112c43ce576f315d5b1b6145b1561259057604051632e1a7d4d60e01b815273a51894664a773981c6c112c43ce576f315d5b1b690632e1a7d4d9061254f908590600401612eb9565b600060405180830381600087803b15801561256957600080fd5b505af115801561257d573d6000803e3d6000fd5b5050505061258b8383612c5b565b61259b565b61259b848484612835565b50505050565b60006125ab611096565b6001600160a01b038616600090815260036020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928992899289929091906125f983613cbb565b919050558760405160200161261396959493929190613cd5565b6040516020818303038152906040528051906020012060405160200161263a929190613d24565b604051602081830303815290604052805190602001209050949350505050565b6000806126678484612cd8565b9050846001600160a01b0316816001600160a01b03160361269b576001600160a01b0381161561269b57600191505061096d565b600080866001600160a01b0316631626ba7e60e01b87876040516024016126c3929190613d55565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516127019190613d97565b600060405180830381855afa9150503d806000811461273c576040519150601f19603f3d011682016040523d82523d6000602084013e612741565b606091505b5091509150818015612754575080516020145b801561277b57508051630b135d3f60e11b906127799083016020908101908401613781565b145b979650505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60046040516127b89190613e15565b6040519081900381206127f492917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69046903090602001613e21565b60405160208183030381529060405280519060200120905090565b6000670de0b6b3a764000061282b6611c37937e0800084613583565b6107ea9190613beb565b600080846001600160a01b031663a9059cbb858560405160240161285a929190613e63565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516128939190613d97565b6000604051808303816000865af19150503d80600081146128d0576040519150601f19603f3d011682016040523d82523d6000602084013e6128d5565b606091505b509150915081158061290357508051158015906129035750808060200190518101906129019190613c9a565b155b15612921576040516312171d8360e31b815260040160405180910390fd5b5050505050565b80156129e55760006129386129e9565b90506001600160a01b038116156129e357612954838284612835565b806001600160a01b031663843e8218600a85856611c37937e0800060026040516020016129819190613c07565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016129b0959493929190613e71565b600060405180830381600087803b1580156129ca57600080fd5b505af11580156129de573d6000803e3d6000fd5b505050505b505b5050565b60007312af3ec993ec5d5bd789b3e989c9e95a2f6c586d6001600160a01b0316634ccb20c06040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612a59575060408051601f3d908101601f19168201909252612a5691810190613e8a565b60015b611b325750600090565b80600080828254612a7491906135a2565b90915550506001600160a01b03821660008181526001602052604080822080548501905551600080516020613ed783398151915290612123908590612eb9565b81810282810482146107ea57600080fd5b8282028381048314612ad657600080fd5b0492915050565b600080612aea83856135a2565b90508015612b9e579050806000600286026000198101825b610100811015612b99576000612b2d612b26612b1f898a8d612d8b565b898b612d8b565b6004900490565b9050869450612b79612b40600283612ab4565b612b4a8689612ab4565b612b5491906135a2565b88612b60600385612ab4565b612b6a878c612ab4565b612b7491906135a2565b612da3565b9650612b858786612db8565b15612b905750612b99565b50600101612b02565b505050505b509392505050565b600080612bbe8384612bb9600288612ab4565b612d8b565b9050612bce818460048802612dda565b90506000612be1600287028504866135a2565b9050600084935060005b610100811015612c50578491508583612c05600288612ab4565b612c0f91906135a2565b612c19919061352a565b84612c248780613583565b612c2e91906135a2565b612c389190613beb565b9450612c448583612db8565b612c5057600101612beb565b505050509392505050565b6000826001600160a01b031682604051612c7490613eab565b60006040518083038185875af1925050503d8060008114612cb1576040519150601f19603f3d011682016040523d82523d6000602084013e612cb6565b606091505b50509050806129e35760405163b12d13eb60e01b815260040160405180910390fd5b60008151604114612ceb575060006107ea565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612d3157600093505050506107ea565b60018682858560405160008152602001604052604051612d549493929190613bc3565b6020604051602081039080840390855afa158015612d76573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b828202811515841585830485141716612ad657600080fd5b828202811515848204841416612ad657600080fd5b600081831115612dcf5750600181830311156107ea565b506001919003111590565b8282028315848204841417612ad657600080fd5b6001600160e01b031981165b8114612e0557600080fd5b50565b80356107ea81612dee565b600060208284031215612e2857612e28600080fd5b6000611a9f8484612e08565b8015155b82525050565b602081016107ea8284612e34565b60005b83811015612e67578181015183820152602001612e4f565b50506000910152565b6000612e7a825190565b808452602084019350612e91818560208601612e4c565b601f01601f19169290920192915050565b6020808252810161096d8184612e70565b80612e38565b602081016107ea8284612eb3565b60408101612ed58285612eb3565b61096d6020830184612eb3565b60006001600160a01b0382166107ea565b612dfa81612ee2565b80356107ea81612ef3565b80612dfa565b80356107ea81612f07565b60008060408385031215612f2e57612f2e600080fd5b6000612f3a8585612efc565b9250506020612f4b85828601612f0d565b9150509250929050565b612e3881612ee2565b602081016107ea8284612f55565b6001600160401b038116612e38565b60808101612f898287612f6c565b612f966020830186612f6c565b612fa36040830185612f6c565b612fb06060830184612f6c565b95945050505050565b600080600060608486031215612fd157612fd1600080fd5b6000612fdd8686612efc565b9350506020612fee86828701612efc565b9250506040612fff86828701612f0d565b9150509250925092565b60008083601f84011261301e5761301e600080fd5b5081356001600160401b0381111561303857613038600080fd5b60208301915083600182028301111561305357613053600080fd5b9250929050565b6000806000806000806080878903121561307657613076600080fd5b86356001600160401b0381111561308f5761308f600080fd5b61309b89828a01613009565b965096505060206130ae89828a01612efc565b94505060406130bf89828a01612efc565b93505060608701356001600160401b038111156130de576130de600080fd5b6130ea89828a01613009565b92509250509295509295509295565b8051604083019061310a8482612f55565b50602082015161259b6020850182612eb3565b604081016107ea82846130f9565b60008060008060008060a0878903121561314757613147600080fd5b60006131538989612efc565b965050602061316489828a01612efc565b955050604061317589828a01612f0d565b945050606061318689828a01612f0d565b93505060808701356001600160401b038111156130de576130de600080fd5b60ff8116612e38565b602081016107ea82846131a5565b60006107ea82612ee2565b612dfa816131bc565b80356107ea816131c7565b634e487b7160e01b600052604160045260246000fd5b601f19601f83011681018181106001600160401b0382111715613216576132166131db565b6040525050565b600061322860405190565b9050611b3282826131f1565b60006001600160401b0382111561324d5761324d6131db565b601f19601f83011660200192915050565b82818337506000910152565b600061327d61327884613234565b61321d565b90508281526020810184848401111561329857613298600080fd5b612b9e84828561325e565b600082601f8301126132b7576132b7600080fd5b8135611a9f84826020860161326a565b600080600080608085870312156132e0576132e0600080fd5b60006132ec87876131d0565b94505060206132fd87828801612efc565b935050604061330e87828801612f0d565b92505060608501356001600160401b0381111561332d5761332d600080fd5b613339878288016132a3565b91505092959194509250565b60006020828403121561335a5761335a600080fd5b6000611a9f8484612efc565b6000806000806080858703121561337f5761337f600080fd5b600061338b8787612efc565b945050602061339c87828801612efc565b935050604061330e87828801612efc565b62ffffff8116612e38565b602081016107ea82846133ad565b61ffff8116612e38565b602081016107ea82846133c6565b602081016107ea8284612f6c565b60ff8116612dfa565b80356107ea816133ec565b600080600080600080600060e0888a03121561341e5761341e600080fd5b600061342a8a8a612efc565b975050602061343b8a828b01612efc565b965050604061344c8a828b01612f0d565b955050606061345d8a828b01612f0d565b945050608061346e8a828b016133f5565b93505060a061347f8a828b01612f0d565b92505060c06134908a828b01612f0d565b91505092959891949750929550565b600080604083850312156134b5576134b5600080fd5b60006134c18585612efc565b9250506020612f4b85828601612efc565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806134fc57607f821691505b60208210810361350e5761350e6134d2565b50919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156107ea576107ea613514565b60008060006060848603121561355557613555600080fd5b60006135618686612efc565b935050602061357286828701612efc565b9250506040612fff868287016133f5565b81810280821583820485141761359b5761359b613514565b5092915050565b808201808211156107ea576107ea613514565b60006107ea6135c18381565b90565b612e38816135b5565b604081016135db8285612eb3565b61096d60208301846135c4565b60408101612ed582856135c4565b805160009061020084019061360b8582612f55565b50602083015161361e6020860182612f55565b5060408301516136316040860182612f55565b5060608301516136446060860182612f55565b5060808301516136576080860182612eb3565b5060a083015161366a60a0860182612eb3565b5060c083015161367d60c0860182612eb3565b5060e083015161369060e0860182612eb3565b506101008301516136a5610100860182612eb3565b506101208301516136ba610120860182612eb3565b506101408301516136cf610140860182612eb3565b506101608301516136e4610160860182612eb3565b506101808301516136f9610180860182612eb3565b506101a083015161370e6101a08601826133ad565b506101c08301516137236101c08601826131a5565b506101e08301518482036101e0860152612fb08282612e70565b6020808252810161096d81846135f6565b6060810161375c8286612eb3565b6137696020830185612eb3565b611a9f6040830184612eb3565b80516107ea81612f07565b60006020828403121561379657613796600080fd5b6000611a9f8484613776565b601f81526000602082017f494e53554646494349454e545f464c4153485f4c4f414e5f42414c414e434500815291505b5060200190565b602080825281016107ea816137a2565b60a081016137f78288612f55565b6138046020830187612f55565b6138116040830186612eb3565b61381e6060830185612eb3565b818103608083015261277b8184612e70565b601881526000602082017f49455243333135365f43414c4c4241434b5f4641494c45440000000000000000815291506137d2565b602080825281016107ea81613830565b601981526000602082017f494e56414c49445f504f53545f4c4f414e5f42414c414e434500000000000000815291506137d2565b602080825281016107ea81613874565b602080825281016107ea81602281527f494e53554646494349454e545f464c4153485f4c4f414e5f4645455f414d4f55602082015261139560f21b604082015260600190565b6080810161390c8287612eb3565b61391960208301866135c4565b61392660408301856135c4565b612fb06060830184612eb3565b6080810161394182876135c4565b61394e6020830186612eb3565b61395b6040830185612eb3565b612fb060608301846135c4565b80516000906101c084019061397d8582612f55565b5060208301516139906020860182612f55565b5060408301516139a36040860182612f55565b5060608301516139b66060860182612f55565b5060808301516139c96080860182612eb3565b5060a08301516139dc60a0860182612eb3565b5060c08301516139ef60c0860182612eb3565b5060e0830151613a0260e0860182612eb3565b50610100830151613a17610100860182612eb3565b50610120830151613a2c610120860182612eb3565b50610140830151613a41610140860182612eb3565b50610160830151613a566101608601826133ad565b50610180830151613a6b6101808601826131a5565b506101a08301518482036101a0860152612fb08282612e70565b6020808252810161096d8184613968565b60808101613aa48287612eb3565b613ab16020830186612eb3565b613abe60408301856133ad565b612fb06060830184612f55565b60a08101613ad98288612f55565b613ae66020830187612f55565b613af36040830186612f55565b61381e6060830185612f55565b62ffffff8116612dfa565b80516107ea81613b00565b600060208284031215613b2b57613b2b600080fd5b6000611a9f8484613b0b565b6001600160401b0391821691908116908282029081169081811461359b5761359b613514565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b03821691506001600160401b0383165b925082613b9b57613b9b613b5d565b500490565b6001600160401b039182169190811690828203908111156107ea576107ea613514565b60808101613bd18287612eb3565b613bde60208301866131a5565b6139266040830185612eb3565b600082613b8c565b600060ff82166107ea565b612e3881613bf3565b602081016107ea8284613bfe565b600061ffff82166107ea565b612e3881613c15565b60006107ea6135c162ffffff841681565b612e3881613c2a565b60a08101613c528288613c21565b613c5f6020830187612f55565b613c6c6040830186612eb3565b61381e6060830185613c3b565b6060810161375c82866133ad565b801515612dfa565b80516107ea81613c87565b600060208284031215613caf57613caf600080fd5b6000611a9f8484613c8f565b60006000198203613cce57613cce613514565b5060010190565b60c08101613ce38289612eb3565b613cf06020830188612f55565b613cfd6040830187612f55565b613d0a6060830186612eb3565b613d176080830185612eb3565b61277b60a0830184612eb3565b61190160f01b81526002016000613d3b8285612eb3565b602082019150613d4b8284612eb3565b5060200192915050565b60408101613d638285612eb3565b8181036020830152611a9f8184612e70565b6000613d7f825190565b613d8d818560208601612e4c565b9290920192915050565b600061096d8284613d75565b60008154613db0816134e8565b600182168015613dc75760018114613ddc57613e0c565b60ff1983168652811515820286019350613e0c565b60008581526020902060005b83811015613e0457815488820152600190910190602001613de8565b838801955050505b50505092915050565b600061096d8284613da3565b60a08101613e2f82886135c4565b613e3c6020830187612eb3565b613e4960408301866135c4565b613e566060830185612eb3565b6124da6080830184612f55565b60408101612ed58285612f55565b60a081016137f78288613c21565b80516107ea81612ef3565b600060208284031215613e9f57613e9f600080fd5b6000611a9f8484613e7f565b60006107ea826135c156fea6205f24a082c01e6c705e20c1a026c246eedf9800b87b84440f05e8271aaf27ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220cea629261ef25ecaf9dbbecf5ef993e24a7a41e9ded4f39619506a562cfa1a1564736f6c63430008170033a26469706673582212205638557b6c917276ad9aacfa583f3fb2452ec9d86c05c2a44572fa1428b4e1cb64736f6c6343000817003300000000000000000000000012af3ec993ec5d5bd789b3e989c9e95a2f6c586d
Deployed Bytecode
0x60806040523480156200001157600080fd5b50600436106200005e5760003560e01c806313b8683f14620000635780634625a94d1462000092578063531aa03e14620000b8578063d039f62214620000ec578063ee97f7f31462000105575b600080fd5b6200007a6200007436600462000649565b6200012d565b604051620000899190620006bb565b60405180910390f35b620000a9620000a3366004620006f2565b62000264565b604051620000899190620007a2565b6200007a620000c9366004620007b2565b60006020818152928152604080822090935290815220546001600160a01b031681565b620000f66200030e565b60405162000089919062000852565b6200007a7f00000000000000000000000012af3ec993ec5d5bd789b3e989c9e95a2f6c586d81565b600080806200013f84860186620007b2565b91509150806001600160a01b0316826001600160a01b03160362000176576040516333910aef60e11b815260040160405180910390fd5b816001600160a01b0316816001600160a01b031610156200019357905b6001600160a01b038216620001bb576040516333910aef60e11b815260040160405180910390fd5b620001c78282620003a8565b6001600160a01b0380841660008181526020818152604080832087861680855290835281842080549688166001600160a01b03199788168117909155848452828520868652909352928190208054909516909117909355915192955090917f9c5d829b9b23efc461f9aeef91979ec04bb903feb3bee4f26d22114abfc7335b9062000254908790620006bb565b60405180910390a3505092915050565b604051634625a94d60e01b81526000906001600160a01b037f00000000000000000000000012af3ec993ec5d5bd789b3e989c9e95a2f6c586d1690634625a94d90620002bf908a908a908a908a908a908a906004016200089e565b602060405180830381865afa158015620002dd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000303919062000915565b979650505050505050565b6060600180546200031f9062000958565b80601f01602080910402602001604051908101604052809291908181526020018280546200034d9062000958565b80156200039e5780601f1062000372576101008083540402835291602001916200039e565b820191906000526020600020905b8154815290600101906020018083116200038057829003601f168201915b5050505050905090565b600080836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015620003ea573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200041091906200099f565b6200041d906012620009da565b6200042a90600a62000b28565b90506000836001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200046d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200049391906200099f565b620004a0906012620009da565b620004ad90600a62000b28565b9050600085858484604051602001620004ca949392919062000b46565b60408051601f1981840301815291905290506001620004ea828262000c54565b5085856040516020016200050092919062000d25565b60408051601f1981840301815290829052805160208201209092509081906200052990620005e3565b8190604051809103906000f59050801580156200054a573d6000803e3d6000fd5b5060405163a5a7f8b760e01b81529095506001600160a01b037f00000000000000000000000012af3ec993ec5d5bd789b3e989c9e95a2f6c586d169063a5a7f8b790620005a590889060029087908d908d9060040162000d5c565b600060405180830381600087803b158015620005c057600080fd5b505af1158015620005d5573d6000803e3d6000fd5b505050505050505092915050565b6149288062000dba83390190565b60008083601f840112620006085762000608600080fd5b50813567ffffffffffffffff811115620006255762000625600080fd5b602083019150836001820283011115620006425762000642600080fd5b9250929050565b60008060208385031215620006615762000661600080fd5b823567ffffffffffffffff8111156200067d576200067d600080fd5b6200068b85828601620005f1565b92509250509250929050565b60006001600160a01b0382165b92915050565b620006b58162000697565b82525050565b60208101620006a48284620006aa565b620006d68162000697565b8114620006e257600080fd5b50565b8035620006a481620006cb565b60008060008060008060a08789031215620007105762000710600080fd5b60006200071e8989620006e5565b96505060206200073189828a01620006e5565b95505060406200074489828a01620006e5565b94505060606200075789828a01620006e5565b935050608087013567ffffffffffffffff811115620007795762000779600080fd5b6200078789828a01620005f1565b92509250509295509295509295565b62ffffff8116620006b5565b60208101620006a4828462000796565b60008060408385031215620007ca57620007ca600080fd5b6000620007d88585620006e5565b9250506020620007eb85828601620006e5565b9150509250929050565b60005b8381101562000812578181015183820152602001620007f8565b50506000910152565b600062000826825190565b8084526020840193506200083f818560208601620007f5565b601f19601f8201165b9093019392505050565b602080825281016200086581846200081b565b9392505050565b82818337506000910152565b8183526000602084019350620008908385846200086c565b601f19601f84011662000848565b60a08101620008ae8289620006aa565b620008bd6020830188620006aa565b620008cc6040830187620006aa565b620008db6060830186620006aa565b8181036080830152620008f081848662000878565b98975050505050505050565b62ffffff8116620006d6565b8051620006a481620008fc565b6000602082840312156200092c576200092c600080fd5b60006200093a848462000908565b949350505050565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806200096d57607f821691505b60208210810362000982576200098262000942565b50919050565b60ff8116620006d6565b8051620006a48162000988565b600060208284031215620009b657620009b6600080fd5b60006200093a848462000992565b634e487b7160e01b600052601160045260246000fd5b60ff918216919081169082820390811115620006a457620006a4620009c4565b80825b600185111562000a405780860481111562000a1c5762000a1c620009c4565b600185161562000a2b57908102905b800262000a388560011c90565b9450620009fd565b94509492505050565b60008262000a5a5750600162000865565b8162000a695750600062000865565b816001811462000a82576002811462000a8d5762000ac1565b600191505062000865565b60ff84111562000aa15762000aa1620009c4565b8360020a91508482111562000aba5762000aba620009c4565b5062000865565b5060208310610133831016604e8410600b841016171562000af9575081810a8381111562000af35762000af3620009c4565b62000865565b62000b088484846001620009fa565b9250905081840481111562000b215762000b21620009c4565b0292915050565b600060ff8316925062000865600019848462000a49565b80620006b5565b6080810162000b568287620006aa565b62000b656020830186620006aa565b62000b74604083018562000b3f565b62000b83606083018462000b3f565b95945050505050565b634e487b7160e01b600052604160045260246000fd5b6000620006a462000bb08381565b90565b62000bbe8362000ba2565b815460001960089490940293841b1916921b91909117905550565b600062000be881848462000bb3565b505050565b8181101562000c0c5762000c0360008262000bd9565b60010162000bed565b5050565b601f82111562000be8576000818152602090206020601f8501048101602085101562000c395750805b62000c4d6020601f86010483018262000bed565b5050505050565b815167ffffffffffffffff81111562000c715762000c7162000b8c565b62000c7d825462000958565b62000c8a82828562000c10565b6020601f83116001811462000cc1576000841562000ca85750858201515b600019600886021c198116600286021786555062000d1d565b600085815260208120601f198616915b8281101562000cf3578885015182556020948501946001909201910162000cd1565b8683101562000d105784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b6040810162000d358285620006aa565b620008656020830184620006aa565b600061ffff8216620006a4565b620006b58162000d44565b60a0810162000d6c8288620006aa565b62000d7b602083018762000d51565b818103604083015262000d8f81866200081b565b905062000da06060830185620006aa565b62000daf6080830184620006aa565b969550505050505056fe610120604052601260805260016008553480156200001c57600080fd5b506000336001600160a01b031663d039f6226040518163ffffffff1660e01b8152600401600060405180830381865afa1580156200005e573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052620000889190810190620004a7565b905060008060008084806020019051810190620000a6919062000535565b61010081905260e08290526001600160a01b0380841660c052841660a052604080516080810182526107d0808252602082015260009181018290526060018190526907d000000000000007d0600b5593975091955093509150806200010b86620001df565b90925090506000806200011e87620001df565b915091508380156200012d5750815b156200018857620001826040516020016200014890620005a3565b60405160208183030381529060405284836040516020016200016c929190620005e9565b60408051601f19818403018152919052620002b7565b620001d0565b620001d0604051806040016040528060038152602001620524c560ec1b815250604051806040016040528060038152602001620524c560ec1b815250620002b760201b60201c565b50505050505050505062000901565b60408051600481526024810182526020810180516001600160e01b03166395d89b4160e01b1790529051600091606091839182916001600160a01b03871691620002299162000623565b600060405180830381855afa9150503d806000811462000266576040519150601f19603f3d011682016040523d82523d6000602084013e6200026b565b606091505b509150915081156200029a576001818060200190518101906200028f9190620004a7565b935093505050915091565b600060405180602001604052806000815250935093505050915091565b6004620002c5838262000730565b506005620002d4828262000730565b5046600655620002e3620002ea565b6007555050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60046040516200031e91906200087a565b6040519081900381206200035c92917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69046903090602001620008ab565b60405160208183030381529060405280519060200120905090565b634e487b7160e01b600052604160045260246000fd5b601f19601f83011681018181106001600160401b0382111715620003b557620003b562000377565b6040525050565b6000620003c860405190565b9050620003d682826200038d565b919050565b60006001600160401b03821115620003f757620003f762000377565b601f19601f83011660200192915050565b60005b83811015620004255781810151838201526020016200040b565b50506000910152565b6000620004456200043f84620003db565b620003bc565b905082815260208101848484011115620004625762000462600080fd5b6200046f84828562000408565b509392505050565b600082601f8301126200048d576200048d600080fd5b81516200049f8482602086016200042e565b949350505050565b600060208284031215620004be57620004be600080fd5b81516001600160401b03811115620004d957620004d9600080fd5b6200049f8482850162000477565b60006001600160a01b0382165b92915050565b6200050581620004e7565b81146200051157600080fd5b50565b8051620004f481620004fa565b8062000505565b8051620004f48162000521565b60008060008060808587031215620005505762000550600080fd5b60006200055e878762000514565b9450506020620005718782880162000514565b9350506040620005848782880162000528565b9250506060620005978782880162000528565b91505092959194509250565b6e0526974737520537461626c65204c5608c1b81526000600f8201620004f4565b6000620005cf825190565b620005df81856020860162000408565b9290920192915050565b6000620005f78285620005c4565b602f60f81b815260010191506200060f8284620005c4565b612d5360f01b81529150600282016200049f565b6000620006318284620005c4565b9392505050565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806200066357607f821691505b60208210810362000678576200067862000638565b50919050565b6000620004f46200068c8381565b90565b6200069a836200067e565b815460001960089490940293841b1916921b91909117905550565b6000620006c48184846200068f565b505050565b81811015620006e857620006df600082620006b5565b600101620006c9565b5050565b601f821115620006c4576000818152602090206020601f85010481016020851015620007155750805b620007296020601f860104830182620006c9565b5050505050565b81516001600160401b038111156200074c576200074c62000377565b6200075882546200064e565b62000765828285620006ec565b6020601f8311600181146200079c5760008415620007835750858201515b600019600886021c1981166002860217865550620007f8565b600085815260208120601f198616915b82811015620007ce5788850151825560209485019460019092019101620007ac565b86831015620007eb5784890151600019601f89166008021c191682555b6001600288020188555050505b505050505050565b600081546200080f816200064e565b6001821680156200082957600181146200083f5762000871565b60ff198316865281151582028601935062000871565b60008581526020902060005b8381101562000869578154888201526001909101906020016200084b565b838801955050505b50505092915050565b600062000631828462000800565b62000893816200067e565b82525050565b8062000893565b6200089381620004e7565b60a08101620008bb828862000888565b620008ca602083018762000899565b620008d9604083018662000888565b620008e8606083018562000899565b620008f76080830184620008a0565b9695505050505050565b60805160a05160c05160e05161010051613f2c620009fc600039600081816104af01528181612240015281816122f90152818161232b01526124a801526000818161065b01528181612212015281816122a101528181612383015261247a01526000818161068f01528181610b4101528181610ba301528181610d0401528181610d60015281816115640152818161159d015281816116c2015281816117080152611e8301526000818161032801528181610b8201528181610bde01528181610cbe01528181610d25015281816115020152818161154301528181611729015281816117620152611dde0152600061043b0152613f2c6000f3fe6080604052600436106102085760003560e01c8063613255ab11610118578063baa8c7cb116100a0578063d6ea073d1161006f578063d6ea073d146106f3578063d9d98ce414610709578063da81573114610729578063dd62ed3e1461073e578063ee97f7f3146107765761020f565b8063baa8c7cb14610649578063d21220a71461067d578063d46300fd146106b1578063d505accf146106d35761020f565b80638b4c5470116100e75780638b4c5470146105b057806395d89b41146105dd578063a5a41031146105f2578063a9059cbb14610607578063b1dd61b6146106275761020f565b8063613255ab1461051657806370a08231146105365780637132bb7f146105635780637ecebe00146105835761020f565b806323b872dd1161019b5780633644e5151161016a5780633644e5151461046a578063443cb4bc1461047f5780634e25dc471461049d5780635a76f25e146104d15780635cffe9de146104f65761020f565b806323b872dd146103bc57806327b0bcea146103dc5780632c0198cc14610409578063313ce567146104295761020f565b8063095ea7b3116101d7578063095ea7b3146102f65780630dfe16811461031657806318160ddd1461035757806319706b381461036d5761020f565b806301ffc9a71461024957806306fdde031461027f57806307f293f7146102a15780630902f1ac146102c45761020f565b3661020f57005b36600080376000803660007360df1f3124128b29d3d595d91cd13de0b84bd9975af43d6000803e808015610242573d6000f35b3d6000fd5b005b34801561025557600080fd5b50610269610264366004612e13565b61079e565b6040516102769190612e3e565b60405180910390f35b34801561028b57600080fd5b506102946107f0565b6040516102769190612ea2565b3480156102ad57600080fd5b506102b7600a5481565b6040516102769190612eb9565b3480156102d057600080fd5b506009546001600160801b0380821691600160801b900416604051610276929190612ec7565b34801561030257600080fd5b50610269610311366004612f18565b61087e565b34801561032257600080fd5b5061034a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516102769190612f5e565b34801561036357600080fd5b506102b760005481565b34801561037957600080fd5b50600b546103ac906001600160401b0380821691600160401b8104821691600160801b8204811691600160c01b90041684565b6040516102769493929190612f7b565b3480156103c857600080fd5b506102696103d7366004612fb9565b610894565b3480156103e857600080fd5b506103fc6103f736600461305a565b610974565b604051610276919061311d565b34801561041557600080fd5b5061024761042436600461312b565b610ff1565b34801561043557600080fd5b5061045d7f000000000000000000000000000000000000000000000000000000000000000081565b60405161027691906131ae565b34801561047657600080fd5b506102b7611096565b34801561048b57600080fd5b506009546001600160801b03166102b7565b3480156104a957600080fd5b506102b77f000000000000000000000000000000000000000000000000000000000000000081565b3480156104dd57600080fd5b50600954600160801b90046001600160801b03166102b7565b34801561050257600080fd5b506102696105113660046132c7565b6110b5565b34801561052257600080fd5b506102b7610531366004613345565b611360565b34801561054257600080fd5b506102b7610551366004613345565b60016020526000908152604090205481565b34801561056f57600080fd5b506103fc61057e36600461305a565b6113d0565b34801561058f57600080fd5b506102b761059e366004613345565b60036020526000908152604090205481565b3480156105bc57600080fd5b506105d06105cb366004613366565b611a15565b60405161027691906133b8565b3480156105e957600080fd5b50610294611aa7565b3480156105fe57600080fd5b506105d0611ab4565b34801561061357600080fd5b50610269610622366004612f18565b611b37565b34801561063357600080fd5b5061063c600281565b60405161027691906133d0565b34801561065557600080fd5b506102b77f000000000000000000000000000000000000000000000000000000000000000081565b34801561068957600080fd5b5061034a7f000000000000000000000000000000000000000000000000000000000000000081565b3480156106bd57600080fd5b506106c6611bac565b60405161027691906133de565b3480156106df57600080fd5b506102476106ee366004613400565b611c71565b3480156106ff57600080fd5b506102b760085481565b34801561071557600080fd5b506102b7610724366004612f18565b611d66565b34801561073557600080fd5b506102b7600281565b34801561074a57600080fd5b506102b761075936600461349f565b600260209081526000928352604080842090915290825290205481565b34801561078257600080fd5b5061034a7312af3ec993ec5d5bd789b3e989c9e95a2f6c586d81565b60006001600160e01b031982166301ffc9a760e01b14806107cf57506001600160e01b0319821663d505accf60e01b145b806107ea57506001600160e01b03198216630b00663360e21b145b92915050565b600480546107fd906134e8565b80601f0160208091040260200160405190810160405280929190818152602001828054610829906134e8565b80156108765780601f1061084b57610100808354040283529160200191610876565b820191906000526020600020905b81548152906001019060200180831161085957829003601f168201915b505050505081565b600061088b338484611d71565b50600192915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001981146108f0576108cb838261352a565b6001600160a01b03861660009081526002602090815260408083203384529091529020555b6001600160a01b0385166000908152600160205260408120805485929061091890849061352a565b90915550506001600160a01b0380851660008181526001602052604090819020805487019055519091871690600080516020613ed78339815191529061095f908790612eb9565b60405180910390a360019150505b9392505050565b604080518082019091526000808252602082015260085460011461099757600080fd5b6002600881905550610a4b60405180610200016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b03168152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b610a578789018961353d565b60ff166101c08401526001600160a01b039081166020840152166060820152610a7e611dd9565b60a083015260808201523060009081526001602052604081205460c0830152610aa5611bac565b6001600160401b031690506000610ac78284608001518560a001516000611eff565b60e085015260c0840151909150600003610ae057600080fd5b610b0183608001518460c00151610af79190613583565b8460e00151900490565b61010084015260a083015160c0840151610b1e91610af791613583565b61012084015260c0830151610b349030906120c4565b610b3d8861212f565b97507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031683606001516001600160a01b031603610cbc57610bc7887f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006121d5565b62ffffff166101a084018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408501526101008401516080850151610c3d9285929091610c2190829061352a565b8761012001518860a00151610c36919061352a565b6001612202565b610180850152610160840181905261012084018051610c5d9083906135a2565b9052506101208301516101408401819052600061010085015260a084018051610c8790839061352a565b905250610180830151604051600080516020613eb783398151915291610caf916000906135cd565b60405180910390a1610e42565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031683606001516001600160a01b031614610cfe57600080fd5b610d49887f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006121d5565b62ffffff166101a084018190526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001660408501526101208401516101008501516080860151610dc693869390929091610daa919061352a565b8761012001518860a00151610dbf919061352a565b6000612202565b610180850152610160840181905261010084018051610de69083906135a2565b90525061010083015161014084018190526000610120850152608084018051610e1090839061352a565b905250610180830151604051600080516020613eb783398151915291610e3991600091906135e8565b60405180910390a15b826101400151600003610e5457600080fd5b610e6683608001518460a001516123b9565b8015610e8357610e7f8284608001518560a00151612472565b600a555b610ea183606001518460200151856101400151866101c001516124e4565b6001600160a01b03871615610f55576001600160a01b0388168352604080516020601f88018190048102820181019092528681529087908790819084018382808284376000920191909152505050506101e0840152604051630eace54160e11b81526001600160a01b03881690631d59ca8290610f2290869060040161373d565b600060405180830381600087803b158015610f3c57600080fd5b505af1158015610f50573d6000803e3d6000fd5b505050505b604051806040016040528084606001516001600160a01b03168152602001846101400151815250935082602001516001600160a01b0316336001600160a01b03167fd175a80c109434bb89948928ab2475a6647c94244cb70002197896423c8833638561010001518661012001518760c00151604051610fd79392919061374e565b60405180910390a350506001600855509695505050505050565b828042111561101357604051630407b05b60e31b815260040160405180910390fd5b6000611021888888886125a1565b9050611064888286868080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061265a92505050565b61108157604051638baa579f60e01b815260040160405180910390fd5b61108c888888611d71565b5050505050505050565b600060065446146110ae576110a9612786565b905090565b5060075490565b60006008546001146110c657600080fd5b60026008556040516370a0823160e01b81526000906001600160a01b038616906370a08231906110fa903090600401612f5e565b602060405180830381865afa158015611117573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061113b9190613781565b905060006111488561280f565b9050848210156111735760405162461bcd60e51b815260040161116a906137d9565b60405180910390fd5b61117e868887612835565b6040516323e30c8b60e01b81527f439148f0bbc682ca079e46d6e2c2f0c1e3b820f1a291b069d8882abf8cf18dd9906001600160a01b038916906323e30c8b906111d49033908b908b9088908c906004016137e9565b6020604051808303816000875af11580156111f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112179190613781565b146112345760405162461bcd60e51b815260040161116a90613864565b6040516370a0823160e01b81526000906001600160a01b038816906370a0823190611263903090600401612f5e565b602060405180830381865afa158015611280573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112a49190613781565b9050828110156112c65760405162461bcd60e51b815260040161116a906138a8565b60006112d2848361352a565b9050828110156112f45760405162461bcd60e51b815260040161116a906138b8565b6112fe8882612928565b876001600160a01b0316896001600160a01b03167f0d7d75e01ab95780d3cd1c8ec0dd6c2ce19e3a20427eec8bf53283b6fb8e95f08984604051611343929190612ec7565b60405180910390a360019450505050506001600855949350505050565b6040516370a0823160e01b81526000906001600160a01b038316906370a082319061138f903090600401612f5e565b602060405180830381865afa1580156113ac573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107ea9190613781565b60408051808201909152600080825260208201526008546001146113f357600080fd5b6002600881905550611499604051806101c0016040528060006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160006001600160a01b0316815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600062ffffff168152602001600060ff168152602001606081525090565b6114a58789018961353d565b60ff166101808401526001600160a01b0390811660208401521660408201526009546001600160801b03600160801b8204811660a08401521660808201526114eb611dd9565b60e083015260c08201526114fe8661212f565b95507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681604001516001600160a01b0316036116c057611588867f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006121d5565b62ffffff166101608201526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166060820152608081015160c08201516115d6919061352a565b6101008201526116126115e7611bac565b6001600160401b031682610160015162ffffff1683610100015184608001518560a001516001612202565b610140830152610120820181905260e08201805161163190839061352a565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d822926116869260009182916138fe565b60405180910390a3600080516020613eb783398151915281610140015160006040516116b39291906135cd565b60405180910390a1611883565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681604001516001600160a01b03161461170257600080fd5b61174d867f00000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000006121d5565b62ffffff166101608201526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016606082015260a081015160e082015161179b919061352a565b6101008201526117d76117ac611bac565b6001600160401b031682610160015162ffffff1683610100015184608001518560a001516000612202565b610140830152610120820181905260c0820180516117f690839061352a565b90525060208101516101008201516101208301516040516001600160a01b039093169233927fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229261184d9260009291908390613933565b60405180910390a3600080516020613eb7833981519152600082610140015160405161187a9291906135e8565b60405180910390a15b6101008101511580159061189b575061012081015115155b6118a457600080fd5b6118b68160c001518260e001516123b9565b6118d4816060015182602001518361012001518461018001516124e4565b6001600160a01b03851615611988576001600160a01b0386168152604080516020601f86018190048102820181019092528481529085908590819084018382808284376000920191909152505050506101a082015260405163608dbcbb60e01b81526001600160a01b0386169063608dbcbb90611955908490600401613a85565b600060405180830381600087803b15801561196f57600080fd5b505af1158015611983573d6000803e3d6000fd5b505050505b6060810180516001600160a01b03908116845261012083018051602080870191909152925161010085015191516101608601519486015160405192851695948c169433947faa077b6dc26efdfd606d4340c04a5a222ff968ec199f0b184f4c0f7a5c8e8d71946119fd94919391929190613a96565b60405180910390a45060016008559695505050505050565b604051634625a94d60e01b81526000907312af3ec993ec5d5bd789b3e989c9e95a2f6c586d90634625a94d90611a579030908990899089908990600401613acb565b602060405180830381865afa925050508015611a90575060408051601f3d908101601f19168201909252611a8d91810190613b16565b60015b611a9c57506032611a9f565b90505b949350505050565b600580546107fd906134e8565b6040516302a64b8360e21b81526000907312af3ec993ec5d5bd789b3e989c9e95a2f6c586d90630a992e0c90611aee903090600401612f5e565b602060405180830381865afa925050508015611b27575060408051601f3d908101601f19168201909252611b2491810190613b16565b60015b611b32575061753090565b919050565b33600090815260016020526040812080548391908390611b5890849061352a565b90915550506001600160a01b03831660008181526001602052604090819020805485019055513390600080516020613ed783398151915290611b9b908690612eb9565b60405180910390a350600192915050565b60408051608081018252600b546001600160401b038082168352600160401b820481166020840152600160801b8204811693830193909352600160c01b900482166060820181905260009242161015611c685780600001516001600160401b031681602001516001600160401b03161015611c6857602081015181516040830151606084015192909103914282900391900380611c498385613b37565b611c539190613b73565b8451611c5f9190613ba0565b94505050505090565b60200151919050565b8380421115611c9357604051630407b05b60e31b815260040160405180910390fd5b6000611ca1898989896125a1565b9050600060018287878760405160008152602001604052604051611cc89493929190613bc3565b6020604051602081039080840390855afa158015611cea573d6000803e3d6000fd5b505050602060405103519050896001600160a01b0316816001600160a01b031614611d2857604051638baa579f60e01b815260040160405180910390fd5b6001600160a01b038116611d4f57604051638baa579f60e01b815260040160405180910390fd5b611d5a8a8a8a611d71565b50505050505050505050565b600061096d8261280f565b6001600160a01b0380841660008181526002602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590611dcc908590612eb9565b60405180910390a3505050565b6000807f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166370a08231306040518263ffffffff1660e01b8152600401611e289190612f5e565b602060405180830381865afa158015611e45573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e699190613781565b6040516370a0823160e01b81529092506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906370a0823190611eb8903090600401612f5e565b602060405180830381865afa158015611ed5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ef99190613781565b90509091565b6000805481611f0c6129e9565b600a546001600160a01b0382161515945090915080156120b95783156120b35784600003611f4257611f3f888888612472565b94505b808511156120ae576000611f54611ab4565b9050600062ffffff8216611f68848961352a565b611f729087613583565b611f7c9190613583565b90506000611f8f8462ffffff8516613583565b88611fa262ffffff8616620186a061352a565b611fac9190613583565b611fb691906135a2565b90506000611fc48284613beb565b905080156120a957611fd68682612a63565b856001600160a01b031663843e821860023084886002604051602001611ffc9190613c07565b6040516020818303038152906040526040518663ffffffff1660e01b815260040161202b959493929190613c44565b600060405180830381600087803b15801561204557600080fd5b505af1925050508015612056575060015b5061206181886135a2565b9650856001600160a01b03167f422815a3c1bfb8dd07ed3e682f42d4d640425d52f0b08da06718c8a2932e280285838a6040516120a093929190613c79565b60405180910390a25b505050505b6120b9565b6000600a555b505094509492505050565b6001600160a01b038216600090815260016020526040812080548392906120ec90849061352a565b90915550506000805482900381556040516001600160a01b03841690600080516020613ed783398151915290612123908590612eb9565b60405180910390a35050565b60006001600160a01b03821633146121ce57604051632af3bd5560e21b81527312af3ec993ec5d5bd789b3e989c9e95a2f6c586d9063abcef55490612178903390600401612f5e565b602060405180830381865afa9250505080156121b1575060408051601f3d908101601f191682019092526121ae91810190613c9a565b60015b6121bc575033919050565b806121c7573361096d565b5090919050565b5033919050565b6000611a9f848484336040516020016121ee9190612f5e565b604051602081830303815290604052611a15565b60008085156123ae5760006122377f000000000000000000000000000000000000000000000000000000000000000087612ab4565b905060006122657f000000000000000000000000000000000000000000000000000000000000000087612ab4565b9050612275888a620186a0612ac5565b92506000612283848a61352a565b905060006122928c8585612add565b905086156123245760006122c67f000000000000000000000000000000000000000000000000000000000000000084612ab4565b6122d090866135a2565b905060006122df8e8385612ba6565b905060016122ed828761352a565b6122f7919061352a565b7f0000000000000000000000000000000000000000000000000000000000000000900497506123a9915050565b60006123507f000000000000000000000000000000000000000000000000000000000000000084612ab4565b61235a90856135a2565b905060006123698e8385612ba6565b90506001612377828861352a565b612381919061352a565b7f00000000000000000000000000000000000000000000000000000000000000009004975050505b505050505b965096945050505050565b6001600160801b038211156123e157604051631a93c68960e11b815260040160405180910390fd5b6001600160801b0381111561240957604051631a93c68960e11b815260040160405180910390fd5b6001600160801b03808316908216600160801b026fffffffffffffffffffffffffffffffff1916176009556040517fcf2aa50876cdfbb541206f89af0ee78d44a2abf8d328e37fa4917f982149848a906124669084908490612ec7565b60405180910390a15050565b60008061249f7f000000000000000000000000000000000000000000000000000000000000000085612ab4565b905060006124cd7f000000000000000000000000000000000000000000000000000000000000000085612ab4565b90506124da868383612add565b9695505050505050565b8060ff16600114801561251357506001600160a01b03841673a51894664a773981c6c112c43ce576f315d5b1b6145b1561259057604051632e1a7d4d60e01b815273a51894664a773981c6c112c43ce576f315d5b1b690632e1a7d4d9061254f908590600401612eb9565b600060405180830381600087803b15801561256957600080fd5b505af115801561257d573d6000803e3d6000fd5b5050505061258b8383612c5b565b61259b565b61259b848484612835565b50505050565b60006125ab611096565b6001600160a01b038616600090815260036020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928992899289929091906125f983613cbb565b919050558760405160200161261396959493929190613cd5565b6040516020818303038152906040528051906020012060405160200161263a929190613d24565b604051602081830303815290604052805190602001209050949350505050565b6000806126678484612cd8565b9050846001600160a01b0316816001600160a01b03160361269b576001600160a01b0381161561269b57600191505061096d565b600080866001600160a01b0316631626ba7e60e01b87876040516024016126c3929190613d55565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199094169390931790925290516127019190613d97565b600060405180830381855afa9150503d806000811461273c576040519150601f19603f3d011682016040523d82523d6000602084013e612741565b606091505b5091509150818015612754575080516020145b801561277b57508051630b135d3f60e11b906127799083016020908101908401613781565b145b979650505050505050565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60046040516127b89190613e15565b6040519081900381206127f492917fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc69046903090602001613e21565b60405160208183030381529060405280519060200120905090565b6000670de0b6b3a764000061282b6611c37937e0800084613583565b6107ea9190613beb565b600080846001600160a01b031663a9059cbb858560405160240161285a929190613e63565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516128939190613d97565b6000604051808303816000865af19150503d80600081146128d0576040519150601f19603f3d011682016040523d82523d6000602084013e6128d5565b606091505b509150915081158061290357508051158015906129035750808060200190518101906129019190613c9a565b155b15612921576040516312171d8360e31b815260040160405180910390fd5b5050505050565b80156129e55760006129386129e9565b90506001600160a01b038116156129e357612954838284612835565b806001600160a01b031663843e8218600a85856611c37937e0800060026040516020016129819190613c07565b6040516020818303038152906040526040518663ffffffff1660e01b81526004016129b0959493929190613e71565b600060405180830381600087803b1580156129ca57600080fd5b505af11580156129de573d6000803e3d6000fd5b505050505b505b5050565b60007312af3ec993ec5d5bd789b3e989c9e95a2f6c586d6001600160a01b0316634ccb20c06040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015612a59575060408051601f3d908101601f19168201909252612a5691810190613e8a565b60015b611b325750600090565b80600080828254612a7491906135a2565b90915550506001600160a01b03821660008181526001602052604080822080548501905551600080516020613ed783398151915290612123908590612eb9565b81810282810482146107ea57600080fd5b8282028381048314612ad657600080fd5b0492915050565b600080612aea83856135a2565b90508015612b9e579050806000600286026000198101825b610100811015612b99576000612b2d612b26612b1f898a8d612d8b565b898b612d8b565b6004900490565b9050869450612b79612b40600283612ab4565b612b4a8689612ab4565b612b5491906135a2565b88612b60600385612ab4565b612b6a878c612ab4565b612b7491906135a2565b612da3565b9650612b858786612db8565b15612b905750612b99565b50600101612b02565b505050505b509392505050565b600080612bbe8384612bb9600288612ab4565b612d8b565b9050612bce818460048802612dda565b90506000612be1600287028504866135a2565b9050600084935060005b610100811015612c50578491508583612c05600288612ab4565b612c0f91906135a2565b612c19919061352a565b84612c248780613583565b612c2e91906135a2565b612c389190613beb565b9450612c448583612db8565b612c5057600101612beb565b505050509392505050565b6000826001600160a01b031682604051612c7490613eab565b60006040518083038185875af1925050503d8060008114612cb1576040519150601f19603f3d011682016040523d82523d6000602084013e612cb6565b606091505b50509050806129e35760405163b12d13eb60e01b815260040160405180910390fd5b60008151604114612ceb575060006107ea565b60208201516040830151606084015160001a7f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0821115612d3157600093505050506107ea565b60018682858560405160008152602001604052604051612d549493929190613bc3565b6020604051602081039080840390855afa158015612d76573d6000803e3d6000fd5b5050604051601f190151979650505050505050565b828202811515841585830485141716612ad657600080fd5b828202811515848204841416612ad657600080fd5b600081831115612dcf5750600181830311156107ea565b506001919003111590565b8282028315848204841417612ad657600080fd5b6001600160e01b031981165b8114612e0557600080fd5b50565b80356107ea81612dee565b600060208284031215612e2857612e28600080fd5b6000611a9f8484612e08565b8015155b82525050565b602081016107ea8284612e34565b60005b83811015612e67578181015183820152602001612e4f565b50506000910152565b6000612e7a825190565b808452602084019350612e91818560208601612e4c565b601f01601f19169290920192915050565b6020808252810161096d8184612e70565b80612e38565b602081016107ea8284612eb3565b60408101612ed58285612eb3565b61096d6020830184612eb3565b60006001600160a01b0382166107ea565b612dfa81612ee2565b80356107ea81612ef3565b80612dfa565b80356107ea81612f07565b60008060408385031215612f2e57612f2e600080fd5b6000612f3a8585612efc565b9250506020612f4b85828601612f0d565b9150509250929050565b612e3881612ee2565b602081016107ea8284612f55565b6001600160401b038116612e38565b60808101612f898287612f6c565b612f966020830186612f6c565b612fa36040830185612f6c565b612fb06060830184612f6c565b95945050505050565b600080600060608486031215612fd157612fd1600080fd5b6000612fdd8686612efc565b9350506020612fee86828701612efc565b9250506040612fff86828701612f0d565b9150509250925092565b60008083601f84011261301e5761301e600080fd5b5081356001600160401b0381111561303857613038600080fd5b60208301915083600182028301111561305357613053600080fd5b9250929050565b6000806000806000806080878903121561307657613076600080fd5b86356001600160401b0381111561308f5761308f600080fd5b61309b89828a01613009565b965096505060206130ae89828a01612efc565b94505060406130bf89828a01612efc565b93505060608701356001600160401b038111156130de576130de600080fd5b6130ea89828a01613009565b92509250509295509295509295565b8051604083019061310a8482612f55565b50602082015161259b6020850182612eb3565b604081016107ea82846130f9565b60008060008060008060a0878903121561314757613147600080fd5b60006131538989612efc565b965050602061316489828a01612efc565b955050604061317589828a01612f0d565b945050606061318689828a01612f0d565b93505060808701356001600160401b038111156130de576130de600080fd5b60ff8116612e38565b602081016107ea82846131a5565b60006107ea82612ee2565b612dfa816131bc565b80356107ea816131c7565b634e487b7160e01b600052604160045260246000fd5b601f19601f83011681018181106001600160401b0382111715613216576132166131db565b6040525050565b600061322860405190565b9050611b3282826131f1565b60006001600160401b0382111561324d5761324d6131db565b601f19601f83011660200192915050565b82818337506000910152565b600061327d61327884613234565b61321d565b90508281526020810184848401111561329857613298600080fd5b612b9e84828561325e565b600082601f8301126132b7576132b7600080fd5b8135611a9f84826020860161326a565b600080600080608085870312156132e0576132e0600080fd5b60006132ec87876131d0565b94505060206132fd87828801612efc565b935050604061330e87828801612f0d565b92505060608501356001600160401b0381111561332d5761332d600080fd5b613339878288016132a3565b91505092959194509250565b60006020828403121561335a5761335a600080fd5b6000611a9f8484612efc565b6000806000806080858703121561337f5761337f600080fd5b600061338b8787612efc565b945050602061339c87828801612efc565b935050604061330e87828801612efc565b62ffffff8116612e38565b602081016107ea82846133ad565b61ffff8116612e38565b602081016107ea82846133c6565b602081016107ea8284612f6c565b60ff8116612dfa565b80356107ea816133ec565b600080600080600080600060e0888a03121561341e5761341e600080fd5b600061342a8a8a612efc565b975050602061343b8a828b01612efc565b965050604061344c8a828b01612f0d565b955050606061345d8a828b01612f0d565b945050608061346e8a828b016133f5565b93505060a061347f8a828b01612f0d565b92505060c06134908a828b01612f0d565b91505092959891949750929550565b600080604083850312156134b5576134b5600080fd5b60006134c18585612efc565b9250506020612f4b85828601612efc565b634e487b7160e01b600052602260045260246000fd5b6002810460018216806134fc57607f821691505b60208210810361350e5761350e6134d2565b50919050565b634e487b7160e01b600052601160045260246000fd5b818103818111156107ea576107ea613514565b60008060006060848603121561355557613555600080fd5b60006135618686612efc565b935050602061357286828701612efc565b9250506040612fff868287016133f5565b81810280821583820485141761359b5761359b613514565b5092915050565b808201808211156107ea576107ea613514565b60006107ea6135c18381565b90565b612e38816135b5565b604081016135db8285612eb3565b61096d60208301846135c4565b60408101612ed582856135c4565b805160009061020084019061360b8582612f55565b50602083015161361e6020860182612f55565b5060408301516136316040860182612f55565b5060608301516136446060860182612f55565b5060808301516136576080860182612eb3565b5060a083015161366a60a0860182612eb3565b5060c083015161367d60c0860182612eb3565b5060e083015161369060e0860182612eb3565b506101008301516136a5610100860182612eb3565b506101208301516136ba610120860182612eb3565b506101408301516136cf610140860182612eb3565b506101608301516136e4610160860182612eb3565b506101808301516136f9610180860182612eb3565b506101a083015161370e6101a08601826133ad565b506101c08301516137236101c08601826131a5565b506101e08301518482036101e0860152612fb08282612e70565b6020808252810161096d81846135f6565b6060810161375c8286612eb3565b6137696020830185612eb3565b611a9f6040830184612eb3565b80516107ea81612f07565b60006020828403121561379657613796600080fd5b6000611a9f8484613776565b601f81526000602082017f494e53554646494349454e545f464c4153485f4c4f414e5f42414c414e434500815291505b5060200190565b602080825281016107ea816137a2565b60a081016137f78288612f55565b6138046020830187612f55565b6138116040830186612eb3565b61381e6060830185612eb3565b818103608083015261277b8184612e70565b601881526000602082017f49455243333135365f43414c4c4241434b5f4641494c45440000000000000000815291506137d2565b602080825281016107ea81613830565b601981526000602082017f494e56414c49445f504f53545f4c4f414e5f42414c414e434500000000000000815291506137d2565b602080825281016107ea81613874565b602080825281016107ea81602281527f494e53554646494349454e545f464c4153485f4c4f414e5f4645455f414d4f55602082015261139560f21b604082015260600190565b6080810161390c8287612eb3565b61391960208301866135c4565b61392660408301856135c4565b612fb06060830184612eb3565b6080810161394182876135c4565b61394e6020830186612eb3565b61395b6040830185612eb3565b612fb060608301846135c4565b80516000906101c084019061397d8582612f55565b5060208301516139906020860182612f55565b5060408301516139a36040860182612f55565b5060608301516139b66060860182612f55565b5060808301516139c96080860182612eb3565b5060a08301516139dc60a0860182612eb3565b5060c08301516139ef60c0860182612eb3565b5060e0830151613a0260e0860182612eb3565b50610100830151613a17610100860182612eb3565b50610120830151613a2c610120860182612eb3565b50610140830151613a41610140860182612eb3565b50610160830151613a566101608601826133ad565b50610180830151613a6b6101808601826131a5565b506101a08301518482036101a0860152612fb08282612e70565b6020808252810161096d8184613968565b60808101613aa48287612eb3565b613ab16020830186612eb3565b613abe60408301856133ad565b612fb06060830184612f55565b60a08101613ad98288612f55565b613ae66020830187612f55565b613af36040830186612f55565b61381e6060830185612f55565b62ffffff8116612dfa565b80516107ea81613b00565b600060208284031215613b2b57613b2b600080fd5b6000611a9f8484613b0b565b6001600160401b0391821691908116908282029081169081811461359b5761359b613514565b634e487b7160e01b600052601260045260246000fd5b60006001600160401b03821691506001600160401b0383165b925082613b9b57613b9b613b5d565b500490565b6001600160401b039182169190811690828203908111156107ea576107ea613514565b60808101613bd18287612eb3565b613bde60208301866131a5565b6139266040830185612eb3565b600082613b8c565b600060ff82166107ea565b612e3881613bf3565b602081016107ea8284613bfe565b600061ffff82166107ea565b612e3881613c15565b60006107ea6135c162ffffff841681565b612e3881613c2a565b60a08101613c528288613c21565b613c5f6020830187612f55565b613c6c6040830186612eb3565b61381e6060830185613c3b565b6060810161375c82866133ad565b801515612dfa565b80516107ea81613c87565b600060208284031215613caf57613caf600080fd5b6000611a9f8484613c8f565b60006000198203613cce57613cce613514565b5060010190565b60c08101613ce38289612eb3565b613cf06020830188612f55565b613cfd6040830187612f55565b613d0a6060830186612eb3565b613d176080830185612eb3565b61277b60a0830184612eb3565b61190160f01b81526002016000613d3b8285612eb3565b602082019150613d4b8284612eb3565b5060200192915050565b60408101613d638285612eb3565b8181036020830152611a9f8184612e70565b6000613d7f825190565b613d8d818560208601612e4c565b9290920192915050565b600061096d8284613d75565b60008154613db0816134e8565b600182168015613dc75760018114613ddc57613e0c565b60ff1983168652811515820286019350613e0c565b60008581526020902060005b83811015613e0457815488820152600190910190602001613de8565b838801955050505b50505092915050565b600061096d8284613da3565b60a08101613e2f82886135c4565b613e3c6020830187612eb3565b613e4960408301866135c4565b613e566060830185612eb3565b6124da6080830184612f55565b60408101612ed58285612f55565b60a081016137f78288613c21565b80516107ea81612ef3565b600060208284031215613e9f57613e9f600080fd5b6000611a9f8484613e7f565b60006107ea826135c156fea6205f24a082c01e6c705e20c1a026c246eedf9800b87b84440f05e8271aaf27ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220cea629261ef25ecaf9dbbecf5ef993e24a7a41e9ded4f39619506a562cfa1a1564736f6c63430008170033a26469706673582212205638557b6c917276ad9aacfa583f3fb2452ec9d86c05c2a44572fa1428b4e1cb64736f6c63430008170033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000012af3ec993ec5d5bd789b3e989c9e95a2f6c586d
-----Decoded View---------------
Arg [0] : _master (address): 0x12AF3Ec993EC5d5bD789b3e989c9E95A2F6c586D
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 00000000000000000000000012af3ec993ec5d5bd789b3e989c9e95a2f6c586d
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.