- Contract name:
- MSwapFactory
- Optimization enabled
- true
- Compiler version
- v0.8.13+commit.abaa5c0e
- Optimization runs
- 5000
- EVM Version
- default
- Verified at
- 2024-07-20T06:17:18.036468Z
contracts/MSwap/MSwapFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
//// Using Uniswap
import "./MSwapPair.sol";
contract MSwapFactory {
address public feeTo;
address public feeToSetter;
// bytes32 public constant INIT_CODE_HASH =
// keccak256(abi.encodePacked(type(UniswapV2Pair).creationCode));
mapping(address => mapping(address => address)) public getPair;
address[] public allPairs;
event PairCreated(
address indexed token0,
address indexed token1,
address pair,
uint256
);
constructor(address _feeToSetter) {
feeToSetter = _feeToSetter;
}
function allPairsLength() external view returns (uint256) {
return allPairs.length;
}
function createPair(address tokenA, address tokenB)
external
returns (address pair)
{
require(tokenA != tokenB, "IDENTICAL_ADDRESSES");
(address token0, address token1) = tokenA < tokenB
? (tokenA, tokenB)
: (tokenB, tokenA);
require(token0 != address(0), "ZERO_ADDRESS");
require(getPair[token0][token1] == address(0), "PAIR_EXISTS"); // single check is sufficient
// bytes memory bytecode = type(UniswapV2Pair).creationCode;
// bytes32 salt = keccak256(abi.encodePacked(token0, token1));
// assembly {
// pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
// }
MSwapPair _pair = new MSwapPair();
pair = address(_pair);
MSwapPair(pair).initialize(token0, token1);
getPair[token0][token1] = pair;
getPair[token1][token0] = pair; // populate mapping in the reverse direction
allPairs.push(pair);
emit PairCreated(token0, token1, pair, allPairs.length);
}
function setFeeTo(address _feeTo) external {
require(msg.sender == feeToSetter, "FORBIDDEN");
feeTo = _feeTo;
}
function setFeeToSetter(address _feeToSetter) external {
require(msg.sender == feeToSetter, "FORBIDDEN");
feeToSetter = _feeToSetter;
}
}
contracts/MSwap/MSwapERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import "../libraries/SafeMath.sol";
contract MSwapERC20 {
using SafeMath for uint256;
string public constant name = "MSwap-V1";
string public constant symbol = "XS-V1";
uint8 public constant decimals = 18;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
mapping(address => uint256) public nonces;
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event Transfer(address indexed from, address indexed to, uint256 value);
function _mint(address to, uint256 value) internal {
totalSupply = totalSupply.add(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(address(0), to, value);
}
function _burn(address from, uint256 value) internal {
balanceOf[from] = balanceOf[from].sub(value);
totalSupply = totalSupply.sub(value);
emit Transfer(from, address(0), value);
}
function _approve(
address owner,
address spender,
uint256 value
) private {
allowance[owner][spender] = value;
emit Approval(owner, spender, value);
}
function _transfer(
address from,
address to,
uint256 value
) private {
balanceOf[from] = balanceOf[from].sub(value);
balanceOf[to] = balanceOf[to].add(value);
emit Transfer(from, to, value);
}
function approve(address spender, uint256 value) external returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transfer(address to, uint256 value) external returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool) {
if (allowance[from][msg.sender] != 2**112 - 1) {
allowance[from][msg.sender] = allowance[from][msg.sender].sub(
value
);
}
_transfer(from, to, value);
return true;
}
}
contracts/MSwap/MSwapPair.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
import "../libraries/Math.sol";
import "../libraries/UQ112x112.sol";
import "../interfaces/IERC20.sol";
import "../interfaces/IMSwapFactory.sol";
import "./MSwapERC20.sol";
contract MSwapPair is MSwapERC20 {
using SafeMath for uint256;
using UQ112x112 for uint224;
uint256 public constant MINIMUM_LIQUIDITY = 10**3;
bytes4 private constant SELECTOR =
bytes4(keccak256(bytes("transfer(address,uint256)")));
address public factory;
address public token0;
address public token1;
uint112 private reserve0; // uses single storage slot, accessible via getReserves
uint112 private reserve1; // uses single storage slot, accessible via getReserves
uint32 private blockTimestampLast; // uses single storage slot, accessible via getReserves
uint256 public price0CumulativeLast;
uint256 public price1CumulativeLast;
uint256 public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event
uint256 private unlocked = 1;
modifier lock() {
require(unlocked == 1, "LOCKED");
unlocked = 0;
_;
unlocked = 1;
}
function getReserves()
public
view
returns (
uint112 _reserve0,
uint112 _reserve1,
uint32 _blockTimestampLast
)
{
_reserve0 = reserve0;
_reserve1 = reserve1;
_blockTimestampLast = blockTimestampLast;
}
function _safeTransfer(
address token,
address to,
uint256 value
) private {
(bool success, bytes memory data) = token.call(
abi.encodeWithSelector(SELECTOR, to, value)
);
require(
success && (data.length == 0 || abi.decode(data, (bool))),
"TRANSFER_FAILED"
);
}
event Mint(address indexed sender, uint256 amount0, uint256 amount1);
event Burn(
address indexed sender,
uint256 amount0,
uint256 amount1,
address indexed to
);
event Swap(
address indexed sender,
uint256 amount0In,
uint256 amount1In,
uint256 amount0Out,
uint256 amount1Out,
address indexed to
);
event Sync(uint112 reserve0, uint112 reserve1);
constructor() {
factory = msg.sender;
}
// called once by the factory at time of deployment
function initialize(address _token0, address _token1) external {
require(msg.sender == factory, "FORBIDDEN"); // sufficient check
token0 = _token0;
token1 = _token1;
}
// update reserves and, on the first call per block, price accumulators
/// --/
function _update(
uint256 balance0,
uint256 balance1,
uint112 _reserve0,
uint112 _reserve1
) private {
require(
balance0 <= (2**112 - 1) && balance1 <= (2**112 - 1),
"OVERFLOW"
);
uint32 blockTimestamp = uint32(block.timestamp % 2**32);
uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
// * never overflows, and + overflow is desired
price0CumulativeLast +=
uint256(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) *
timeElapsed;
price1CumulativeLast +=
uint256(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) *
timeElapsed;
}
reserve0 = uint112(balance0);
reserve1 = uint112(balance1);
blockTimestampLast = blockTimestamp;
emit Sync(reserve0, reserve1);
}
// if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k)
// --/
function _collectFee(uint112 _reserve0, uint112 _reserve1)
private
returns (bool feeOn)
{
address feeTo = IMSwapFactory(factory).feeTo();
feeOn = feeTo != address(0);
uint256 _kLast = kLast; // gas savings
if (feeOn) {
if (_kLast != 0) {
uint256 rootK = Math.sqrt(uint256(_reserve0).mul(_reserve1));
uint256 rootKLast = Math.sqrt(_kLast);
if (rootK > rootKLast) {
uint256 numerator = totalSupply.mul(rootK.sub(rootKLast));
uint256 denominator = rootK.mul(5).add(rootKLast);
uint256 liquidity = numerator / denominator;
if (liquidity > 0) _mint(feeTo, liquidity);
}
}
} else if (_kLast != 0) {
kLast = 0;
}
}
// this low-level function should be called from a contract which performs important safety checks
// --/
function mint(address to) external lock returns (uint256 liquidity) {
(uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings
uint256 balance0 = IERC20(token0).balanceOf(address(this));
uint256 balance1 = IERC20(token1).balanceOf(address(this));
uint256 amount0 = balance0.sub(_reserve0);
uint256 amount1 = balance1.sub(_reserve1);
bool feeOn = _collectFee(_reserve0, _reserve1);
uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _collectFee
if (_totalSupply == 0) {
liquidity = Math.sqrt(amount0.mul(amount1)).sub(MINIMUM_LIQUIDITY);
_mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
} else {
liquidity = Math.min(
amount0.mul(_totalSupply) / _reserve0,
amount1.mul(_totalSupply) / _reserve1
);
}
require(liquidity > 0, " INSUFFICIENT_LIQUIDITY_MINTED");
_mint(to, liquidity);
_update(balance0, balance1, _reserve0, _reserve1);
if (feeOn) kLast = uint256(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
emit Mint(msg.sender, amount0, amount1);
}
// this low-level function should be called from a contract which performs important safety checks
// --/
function burn(address to)
external
lock
returns (uint256 amount0, uint256 amount1)
{
(uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings
address _token0 = token0; // gas savings
address _token1 = token1; // gas savings
uint256 balance0 = IERC20(_token0).balanceOf(address(this));
uint256 balance1 = IERC20(_token1).balanceOf(address(this));
uint256 liquidity = balanceOf[address(this)];
bool feeOn = _collectFee(_reserve0, _reserve1);
uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _collectFee
amount0 = liquidity.mul(balance0) / _totalSupply; // using balances ensures pro-rata distribution
amount1 = liquidity.mul(balance1) / _totalSupply; // using balances ensures pro-rata distribution
require(amount0 > 0 && amount1 > 0, "INSUFFICIENT_LIQUIDITY_BURNED");
_burn(address(this), liquidity);
_safeTransfer(_token0, to, amount0);
_safeTransfer(_token1, to, amount1);
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
_update(balance0, balance1, _reserve0, _reserve1);
if (feeOn) kLast = uint256(reserve0).mul(reserve1); // reserve0 and reserve1 are up-to-date
emit Burn(msg.sender, amount0, amount1, to);
}
// this low-level function should be called from a contract which performs important safety checks
// --/
function swap(
uint256 amount0Out,
uint256 amount1Out,
address to,
bytes calldata data
) external lock {
require(amount0Out > 0 || amount1Out > 0, "INSUFFICIENT_OUTPUT_AMOUNT");
(uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings
require(
amount0Out < _reserve0 && amount1Out < _reserve1,
"INSUFFICIENT_LIQUIDITY"
);
uint256 balance0;
uint256 balance1;
{
// scope for _token{0,1}, avoids stack too deep errors
address _token0 = token0;
address _token1 = token1;
require(to != _token0 && to != _token1, "INVALID_TO");
if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
balance0 = IERC20(_token0).balanceOf(address(this));
balance1 = IERC20(_token1).balanceOf(address(this));
}
uint256 amount0In = balance0 > _reserve0 - amount0Out
? balance0 - (_reserve0 - amount0Out)
: 0;
uint256 amount1In = balance1 > _reserve1 - amount1Out
? balance1 - (_reserve1 - amount1Out)
: 0;
require(amount0In > 0 || amount1In > 0, "INSUFFICIENT_INPUT_AMOUNT");
{
// scope for reserve{0,1}Adjusted, avoids stack too deep errors
uint256 balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
uint256 balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));
require(
balance0Adjusted.mul(balance1Adjusted) >=
uint256(_reserve0).mul(_reserve1).mul(1000**2),
" K"
);
}
_update(balance0, balance1, _reserve0, _reserve1);
emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
}
// force balances to match reserves --/
function skim(address to) external lock {
address _token0 = token0; // gas savings
address _token1 = token1; // gas savings
_safeTransfer(
_token0,
to,
IERC20(_token0).balanceOf(address(this)).sub(reserve0)
);
_safeTransfer(
_token1,
to,
IERC20(_token1).balanceOf(address(this)).sub(reserve1)
);
}
// force reserves to match balances --/
function sync() external lock {
_update(
IERC20(token0).balanceOf(address(this)),
IERC20(token1).balanceOf(address(this)),
reserve0,
reserve1
);
}
}
contracts/interfaces/IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
interface IERC20 {
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event Transfer(address indexed from, address indexed to, uint256 value);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
function allowance(address owner, address spender)
external
view
returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transfer(address to, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}
contracts/interfaces/IMSwapFactory.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
interface IMSwapFactory {
event PairCreated(
address indexed token0,
address indexed token1,
address pair,
uint256
);
function feeTo() external view returns (address);
function feeToSetter() external view returns (address);
function getPair(address tokenA, address tokenB)
external
view
returns (address pair);
function allPairs(uint256) external view returns (address pair);
function allPairsLength() external view returns (uint256);
function createPair(address tokenA, address tokenB)
external
returns (address pair);
function setFeeTo(address) external;
function setFeeToSetter(address) external;
}
contracts/libraries/Math.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
// a library for performing various math operations
library Math {
function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = x < y ? x : y;
}
// babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
function sqrt(uint256 y) internal pure returns (uint256 z) {
if (y > 3) {
z = y;
uint256 x = y / 2 + 1;
while (x < z) {
z = x;
x = (y / x + x) / 2;
}
} else if (y != 0) {
z = 1;
}
}
}
contracts/libraries/SafeMath.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)
library SafeMath {
function add(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x + y) >= x, "ds-math-add-overflow");
}
function sub(uint256 x, uint256 y) internal pure returns (uint256 z) {
require((z = x - y) <= x, "ds-math-sub-underflow");
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 z) {
require(y == 0 || (z = x * y) / y == x, "ds-math-mul-overflow");
}
}
contracts/libraries/UQ112x112.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.10;
// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
// range: [0, 2**112 - 1]
// resolution: 1 / 2**112
library UQ112x112 {
uint224 constant Q112 = 2**112;
// encode a uint112 as a UQ112x112
function encode(uint112 y) internal pure returns (uint224 z) {
z = uint224(y) * Q112; // never overflows
}
// divide a UQ112x112 by a uint112, returning a UQ112x112
function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
z = x / uint224(y);
}
}
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata","devdoc","userdoc","storageLayout","evm.gasEstimates"],"":["ast"]}},"optimizer":{"runs":5000,"enabled":true},"metadata":{"useLiteralContent":true},"libraries":{}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_feeToSetter","internalType":"address"}]},{"type":"event","name":"PairCreated","inputs":[{"type":"address","name":"token0","internalType":"address","indexed":true},{"type":"address","name":"token1","internalType":"address","indexed":true},{"type":"address","name":"pair","internalType":"address","indexed":false},{"type":"uint256","name":"","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"allPairs","inputs":[{"type":"uint256","name":"","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allPairsLength","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"address","name":"pair","internalType":"address"}],"name":"createPair","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"feeTo","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"feeToSetter","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getPair","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFeeTo","inputs":[{"type":"address","name":"_feeTo","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFeeToSetter","inputs":[{"type":"address","name":"_feeToSetter","internalType":"address"}]}]
Contract Creation Code
0x608060405234801561001057600080fd5b50604051612b3c380380612b3c83398101604081905261002f91610054565b600180546001600160a01b0319166001600160a01b0392909216919091179055610084565b60006020828403121561006657600080fd5b81516001600160a01b038116811461007d57600080fd5b9392505050565b612aa9806100936000396000f3fe608060405234801561001057600080fd5b50600436106100885760003560e01c8063a2e74af61161005b578063a2e74af61461011b578063c9c6539614610130578063e6a4390514610143578063f46901ed1461018457600080fd5b8063017e7e581461008d578063094b7415146100d75780631e3dd18b146100f7578063574f2ba31461010a575b600080fd5b6000546100ad9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6001546100ad9073ffffffffffffffffffffffffffffffffffffffff1681565b6100ad610105366004610714565b610197565b6003546040519081526020016100ce565b61012e610129366004610756565b6101ce565b005b6100ad61013e366004610778565b61029b565b6100ad610151366004610778565b600260209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff1681565b61012e610192366004610756565b61063f565b600381815481106101a757600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60015473ffffffffffffffffffffffffffffffffffffffff163314610254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f464f5242494444454e000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610332576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4944454e544943414c5f41444452455353455300000000000000000000000000604482015260640161024b565b6000808373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161061036f578385610372565b84845b909250905073ffffffffffffffffffffffffffffffffffffffff82166103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a45524f5f414444524553530000000000000000000000000000000000000000604482015260640161024b565b73ffffffffffffffffffffffffffffffffffffffff828116600090815260026020908152604080832085851684529091529020541615610490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f504149525f455849535453000000000000000000000000000000000000000000604482015260640161024b565b600060405161049e90610707565b604051809103906000f0801580156104ba573d6000803e3d6000fd5b506040517f485cc95500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015284811660248301529195508592509082169063485cc95590604401600060405180830381600087803b15801561053357600080fd5b505af1158015610547573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff83811660008181526002602081815260408084208887168086529083528185208054978c167fffffffffffffffffffffffff000000000000000000000000000000000000000098891681179091559383528185208686528352818520805488168517905560038054600181018255958190527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9095018054909716841790965592548351928352908201527f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9910160405180910390a350505092915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146106c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f464f5242494444454e0000000000000000000000000000000000000000000000604482015260640161024b565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6122c8806107ac83390190565b60006020828403121561072657600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461075157600080fd5b919050565b60006020828403121561076857600080fd5b6107718261072d565b9392505050565b6000806040838503121561078b57600080fd5b6107948361072d565b91506107a26020840161072d565b9050925092905056fe60806040526001600b5534801561001557600080fd5b50600480546001600160a01b03191633179055612291806100376000396000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c806370a08231116100e3578063ba9a7a561161008c578063d21220a711610066578063d21220a714610423578063dd62ed3e14610436578063fff6cae91461046157600080fd5b8063ba9a7a56146103f4578063bc25cf77146103fd578063c45a01551461041057600080fd5b806389afcb44116100bd57806389afcb441461037d57806395d89b41146103a5578063a9059cbb146103e157600080fd5b806370a08231146103345780637464fc3d146103545780637ecebe001461035d57600080fd5b806323b872dd116101455780635909c0d51161011f5780635909c0d51461030f5780635a3d5493146103185780636a6278421461032157600080fd5b806323b872dd146102cf578063313ce567146102e2578063485cc955146102fc57600080fd5b8063095ea7b311610176578063095ea7b31461026a5780630dfe16811461028d57806318160ddd146102b857600080fd5b8063022c0d9f1461019d57806306fdde03146101b25780630902f1ac14610204575b600080fd5b6101b06101ab366004611e77565b610469565b005b6101ee6040518060400160405280600881526020017f4d537761702d563100000000000000000000000000000000000000000000000081525081565b6040516101fb9190611f3d565b60405180910390f35b600754604080516dffffffffffffffffffffffffffff80841682526e01000000000000000000000000000084041660208201527c010000000000000000000000000000000000000000000000000000000090920463ffffffff16908201526060016101fb565b61027d610278366004611f8e565b6109a5565b60405190151581526020016101fb565b6005546102a0906001600160a01b031681565b6040516001600160a01b0390911681526020016101fb565b6102c160005481565b6040519081526020016101fb565b61027d6102dd366004611fba565b6109bc565b6102ea601281565b60405160ff90911681526020016101fb565b6101b061030a366004611ffb565b610a5c565b6102c160085481565b6102c160095481565b6102c161032f366004612034565b610afc565b6102c1610342366004612034565b60016020526000908152604090205481565b6102c1600a5481565b6102c161036b366004612034565b60036020526000908152604090205481565b61039061038b366004612034565b610e2f565b604080519283526020830191909152016101fb565b6101ee6040518060400160405280600581526020017f58532d563100000000000000000000000000000000000000000000000000000081525081565b61027d6103ef366004611f8e565b6111e8565b6102c16103e881565b6101b061040b366004612034565b6111f5565b6004546102a0906001600160a01b031681565b6006546102a0906001600160a01b031681565b6102c1610444366004611ffb565b600260209081526000928352604080842090915290825290205481565b6101b0611352565b600b546001146104c05760405162461bcd60e51b815260206004820152600660248201527f4c4f434b4544000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6000600b55841515806104d35750600084115b61051f5760405162461bcd60e51b815260206004820152601a60248201527f494e53554646494349454e545f4f55545055545f414d4f554e5400000000000060448201526064016104b7565b60008061057b6007546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b5091509150816dffffffffffffffffffffffffffff16871080156105ae5750806dffffffffffffffffffffffffffff1686105b6105fa5760405162461bcd60e51b815260206004820152601660248201527f494e53554646494349454e545f4c49515549444954590000000000000000000060448201526064016104b7565b60055460065460009182916001600160a01b039182169190811690891682148015906106385750806001600160a01b0316896001600160a01b031614155b6106845760405162461bcd60e51b815260206004820152600a60248201527f494e56414c49445f544f0000000000000000000000000000000000000000000060448201526064016104b7565b8a1561069557610695828a8d6114b8565b89156106a6576106a6818a8c6114b8565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156106ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070e9190612051565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610755573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107799190612051565b92505050600089856dffffffffffffffffffffffffffff1661079b9190612099565b83116107a85760006107cc565b6107c28a6dffffffffffffffffffffffffffff8716612099565b6107cc9084612099565b905060006107ea8a6dffffffffffffffffffffffffffff8716612099565b83116107f757600061081b565b6108118a6dffffffffffffffffffffffffffff8716612099565b61081b9084612099565b9050600082118061082c5750600081115b6108785760405162461bcd60e51b815260206004820152601960248201527f494e53554646494349454e545f494e5055545f414d4f554e540000000000000060448201526064016104b7565b600061089a610888846003611631565b610894876103e8611631565b906116a1565b905060006108ac610888846003611631565b90506108d8620f42406108d26dffffffffffffffffffffffffffff8b8116908b16611631565b90611631565b6108e28383611631565b10156109305760405162461bcd60e51b815260206004820152600260248201527f204b00000000000000000000000000000000000000000000000000000000000060448201526064016104b7565b505061093e848488886116ff565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001600b55505050505050505050565b60006109b23384846119c1565b5060015b92915050565b6001600160a01b03831660009081526002602090815260408083203384529091528120546dffffffffffffffffffffffffffff14610a47576001600160a01b0384166000908152600260209081526040808320338452909152902054610a2290836116a1565b6001600160a01b03851660009081526002602090815260408083203384529091529020555b610a52848484611a23565b5060019392505050565b6004546001600160a01b03163314610ab65760405162461bcd60e51b815260206004820152600960248201527f464f5242494444454e000000000000000000000000000000000000000000000060448201526064016104b7565b600580546001600160a01b039384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560068054929093169116179055565b6000600b54600114610b505760405162461bcd60e51b815260206004820152600660248201527f4c4f434b4544000000000000000000000000000000000000000000000000000060448201526064016104b7565b6000600b819055600754600554604080516370a0823160e01b815230600482015290516dffffffffffffffffffffffffffff808516956e0100000000000000000000000000009095041693926001600160a01b0316916370a082319160248083019260209291908290030181865afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190612051565b6006546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c669190612051565b90506000610c84836dffffffffffffffffffffffffffff87166116a1565b90506000610ca2836dffffffffffffffffffffffffffff87166116a1565b90506000610cb08787611ac9565b60008054919250819003610cea57610cd66103e8610894610cd18787611631565b611c19565b9850610ce560006103e8611c89565b610d3f565b610d3c6dffffffffffffffffffffffffffff8916610d088684611631565b610d1291906120df565b6dffffffffffffffffffffffffffff8916610d2d8685611631565b610d3791906120df565b611d18565b98505b60008911610d8f5760405162461bcd60e51b815260206004820152601e60248201527f20494e53554646494349454e545f4c49515549444954595f4d494e544544000060448201526064016104b7565b610d998a8a611c89565b610da586868a8a6116ff565b8115610de157600754610ddd906dffffffffffffffffffffffffffff808216916e010000000000000000000000000000900416611631565b600a555b604080518581526020810185905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001600b5550949695505050505050565b600080600b54600114610e845760405162461bcd60e51b815260206004820152600660248201527f4c4f434b4544000000000000000000000000000000000000000000000000000060448201526064016104b7565b6000600b819055600754600554600654604080516370a0823160e01b815230600482015290516dffffffffffffffffffffffffffff808616966e01000000000000000000000000000090960416946001600160a01b0394851694909316929184916370a08231916024808201926020929091908290030181865afa158015610f10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f349190612051565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610f7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa29190612051565b30600090815260016020526040812054919250610fbf8888611ac9565b60005490915080610fd08487611631565b610fda91906120df565b9a5080610fe78486611631565b610ff191906120df565b995060008b118015611003575060008a115b61104f5760405162461bcd60e51b815260206004820152601d60248201527f494e53554646494349454e545f4c49515549444954595f4255524e454400000060448201526064016104b7565b6110593084611d30565b611064878d8d6114b8565b61106f868d8c6114b8565b6040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa1580156110b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d79190612051565b6040516370a0823160e01b81523060048201529095506001600160a01b038716906370a0823190602401602060405180830381865afa15801561111e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111429190612051565b935061115085858b8b6116ff565b811561118c57600754611188906dffffffffffffffffffffffffffff808216916e010000000000000000000000000000900416611631565b600a555b604080518c8152602081018c90526001600160a01b038e169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050505050505050506001600b81905550915091565b60006109b2338484611a23565b600b546001146112475760405162461bcd60e51b815260206004820152600660248201527f4c4f434b4544000000000000000000000000000000000000000000000000000060448201526064016104b7565b6000600b556005546006546007546040516370a0823160e01b81523060048201526001600160a01b0393841693909216916112e991849186916112e4916dffffffffffffffffffffffffffff9091169084906370a08231906024015b602060405180830381865afa1580156112c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108949190612051565b6114b8565b6007546040516370a0823160e01b815230600482015261134891839186916112e4916e0100000000000000000000000000009091046dffffffffffffffffffffffffffff16906001600160a01b038516906370a08231906024016112a3565b50506001600b5550565b600b546001146113a45760405162461bcd60e51b815260206004820152600660248201527f4c4f434b4544000000000000000000000000000000000000000000000000000060448201526064016104b7565b6000600b556005546040516370a0823160e01b81523060048201526114b1916001600160a01b0316906370a0823190602401602060405180830381865afa1580156113f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114179190612051565b6006546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561145f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114839190612051565b6007546dffffffffffffffffffffffffffff808216916e0100000000000000000000000000009004166116ff565b6001600b55565b604080518082018252601981527f7472616e7366657228616464726573732c75696e74323536290000000000000060209182015281516001600160a01b0385811660248301526044808301869052845180840390910181526064909201845291810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839287169161157291906120f3565b6000604051808303816000865af19150503d80600081146115af576040519150601f19603f3d011682016040523d82523d6000602084013e6115b4565b606091505b50915091508180156115de5750805115806115de5750808060200190518101906115de919061210f565b61162a5760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016104b7565b5050505050565b6000811580611655575082826116478183612131565b925061165390836120df565b145b6109b65760405162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f7700000000000000000000000060448201526064016104b7565b6000826116ae8382612099565b91508111156109b65760405162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f77000000000000000000000060448201526064016104b7565b6dffffffffffffffffffffffffffff841115801561172b57506dffffffffffffffffffffffffffff8311155b6117775760405162461bcd60e51b815260206004820152600860248201527f4f564552464c4f5700000000000000000000000000000000000000000000000060448201526064016104b7565b60006117886401000000004261216e565b6007549091506000906117c1907c0100000000000000000000000000000000000000000000000000000000900463ffffffff1683612182565b905060008163ffffffff161180156117e857506dffffffffffffffffffffffffffff841615155b801561180357506dffffffffffffffffffffffffffff831615155b156118d1578063ffffffff166118408561181c86611dba565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690611de5565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166118689190612131565b6008600082825461187991906121a7565b909155505063ffffffff81166118928461181c87611dba565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166118ba9190612131565b600960008282546118cb91906121a7565b90915550505b6007805463ffffffff84167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff8981166e0100000000000000000000000000009081027fffffffff000000000000000000000000000000000000000000000000000000009095168c83161794909417918216831794859055604080519382169282169290921783529290930490911660208201527f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a1505050505050565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038316600090815260016020526040902054611a4690826116a1565b6001600160a01b038085166000908152600160205260408082209390935590841681522054611a759082611e01565b6001600160a01b0380841660008181526001602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611a169085815260200190565b60048054604080517f017e7e58000000000000000000000000000000000000000000000000000000008152905160009384936001600160a01b03169263017e7e5892818301926020928290030181865afa158015611b2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b4f91906121bf565b600a546001600160a01b038216158015945091925090611c05578015611c00576000611b91610cd16dffffffffffffffffffffffffffff888116908816611631565b90506000611b9e83611c19565b905080821115611bfd576000611bc0611bb784846116a1565b60005490611631565b90506000611bd983611bd3866005611631565b90611e01565b90506000611be782846120df565b90508015611bf957611bf98782611c89565b5050505b50505b611c11565b8015611c11576000600a555b505092915050565b60006003821115611c7a5750806000611c336002836120df565b611c3e9060016121a7565b90505b81811015611c7457905080600281611c5981866120df565b611c6391906121a7565b611c6d91906120df565b9050611c41565b50919050565b8115611c84575060015b919050565b600054611c969082611e01565b60009081556001600160a01b038316815260016020526040902054611cbb9082611e01565b6001600160a01b0383166000818152600160205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611d0c9085815260200190565b60405180910390a35050565b6000818310611d275781611d29565b825b9392505050565b6001600160a01b038216600090815260016020526040902054611d5390826116a1565b6001600160a01b03831660009081526001602052604081209190915554611d7a90826116a1565b60009081556040518281526001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611d0c565b60006109b66e0100000000000000000000000000006dffffffffffffffffffffffffffff84166121dc565b6000611d296dffffffffffffffffffffffffffff831684612220565b600082611e0e83826121a7565b91508110156109b65760405162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f7700000000000000000000000060448201526064016104b7565b6001600160a01b0381168114611e7457600080fd5b50565b600080600080600060808688031215611e8f57600080fd5b85359450602086013593506040860135611ea881611e5f565b9250606086013567ffffffffffffffff80821115611ec557600080fd5b818801915088601f830112611ed957600080fd5b813581811115611ee857600080fd5b896020828501011115611efa57600080fd5b9699959850939650602001949392505050565b60005b83811015611f28578181015183820152602001611f10565b83811115611f37576000848401525b50505050565b6020815260008251806020840152611f5c816040850160208701611f0d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008060408385031215611fa157600080fd5b8235611fac81611e5f565b946020939093013593505050565b600080600060608486031215611fcf57600080fd5b8335611fda81611e5f565b92506020840135611fea81611e5f565b929592945050506040919091013590565b6000806040838503121561200e57600080fd5b823561201981611e5f565b9150602083013561202981611e5f565b809150509250929050565b60006020828403121561204657600080fd5b8135611d2981611e5f565b60006020828403121561206357600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156120ab576120ab61206a565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826120ee576120ee6120b0565b500490565b60008251612105818460208701611f0d565b9190910192915050565b60006020828403121561212157600080fd5b81518015158114611d2957600080fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156121695761216961206a565b500290565b60008261217d5761217d6120b0565b500690565b600063ffffffff8381169083168181101561219f5761219f61206a565b039392505050565b600082198211156121ba576121ba61206a565b500190565b6000602082840312156121d157600080fd5b8151611d2981611e5f565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff808316818516818304811182151516156122175761221761206a565b02949350505050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8084168061224f5761224f6120b0565b9216919091049291505056fea26469706673582212208f5e1f3ab66590215bedfca74b3a139254aed52eb2994dc46a64d6f64788e5e664736f6c634300080d0033a2646970667358221220dc3447b660f115ca2c41f1d62f090981fd42ebd2dec5567d9228e408a96d83eb64736f6c634300080d00330000000000000000000000008df97eab2651e87a8a4080008ddabf6824c9f672
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100885760003560e01c8063a2e74af61161005b578063a2e74af61461011b578063c9c6539614610130578063e6a4390514610143578063f46901ed1461018457600080fd5b8063017e7e581461008d578063094b7415146100d75780631e3dd18b146100f7578063574f2ba31461010a575b600080fd5b6000546100ad9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b6001546100ad9073ffffffffffffffffffffffffffffffffffffffff1681565b6100ad610105366004610714565b610197565b6003546040519081526020016100ce565b61012e610129366004610756565b6101ce565b005b6100ad61013e366004610778565b61029b565b6100ad610151366004610778565b600260209081526000928352604080842090915290825290205473ffffffffffffffffffffffffffffffffffffffff1681565b61012e610192366004610756565b61063f565b600381815481106101a757600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60015473ffffffffffffffffffffffffffffffffffffffff163314610254576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f464f5242494444454e000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610332576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4944454e544943414c5f41444452455353455300000000000000000000000000604482015260640161024b565b6000808373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff161061036f578385610372565b84845b909250905073ffffffffffffffffffffffffffffffffffffffff82166103f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f5a45524f5f414444524553530000000000000000000000000000000000000000604482015260640161024b565b73ffffffffffffffffffffffffffffffffffffffff828116600090815260026020908152604080832085851684529091529020541615610490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f504149525f455849535453000000000000000000000000000000000000000000604482015260640161024b565b600060405161049e90610707565b604051809103906000f0801580156104ba573d6000803e3d6000fd5b506040517f485cc95500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116600483015284811660248301529195508592509082169063485cc95590604401600060405180830381600087803b15801561053357600080fd5b505af1158015610547573d6000803e3d6000fd5b5050505073ffffffffffffffffffffffffffffffffffffffff83811660008181526002602081815260408084208887168086529083528185208054978c167fffffffffffffffffffffffff000000000000000000000000000000000000000098891681179091559383528185208686528352818520805488168517905560038054600181018255958190527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9095018054909716841790965592548351928352908201527f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9910160405180910390a350505092915050565b60015473ffffffffffffffffffffffffffffffffffffffff1633146106c0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f464f5242494444454e0000000000000000000000000000000000000000000000604482015260640161024b565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6122c8806107ac83390190565b60006020828403121561072657600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461075157600080fd5b919050565b60006020828403121561076857600080fd5b6107718261072d565b9392505050565b6000806040838503121561078b57600080fd5b6107948361072d565b91506107a26020840161072d565b9050925092905056fe60806040526001600b5534801561001557600080fd5b50600480546001600160a01b03191633179055612291806100376000396000f3fe608060405234801561001057600080fd5b50600436106101985760003560e01c806370a08231116100e3578063ba9a7a561161008c578063d21220a711610066578063d21220a714610423578063dd62ed3e14610436578063fff6cae91461046157600080fd5b8063ba9a7a56146103f4578063bc25cf77146103fd578063c45a01551461041057600080fd5b806389afcb44116100bd57806389afcb441461037d57806395d89b41146103a5578063a9059cbb146103e157600080fd5b806370a08231146103345780637464fc3d146103545780637ecebe001461035d57600080fd5b806323b872dd116101455780635909c0d51161011f5780635909c0d51461030f5780635a3d5493146103185780636a6278421461032157600080fd5b806323b872dd146102cf578063313ce567146102e2578063485cc955146102fc57600080fd5b8063095ea7b311610176578063095ea7b31461026a5780630dfe16811461028d57806318160ddd146102b857600080fd5b8063022c0d9f1461019d57806306fdde03146101b25780630902f1ac14610204575b600080fd5b6101b06101ab366004611e77565b610469565b005b6101ee6040518060400160405280600881526020017f4d537761702d563100000000000000000000000000000000000000000000000081525081565b6040516101fb9190611f3d565b60405180910390f35b600754604080516dffffffffffffffffffffffffffff80841682526e01000000000000000000000000000084041660208201527c010000000000000000000000000000000000000000000000000000000090920463ffffffff16908201526060016101fb565b61027d610278366004611f8e565b6109a5565b60405190151581526020016101fb565b6005546102a0906001600160a01b031681565b6040516001600160a01b0390911681526020016101fb565b6102c160005481565b6040519081526020016101fb565b61027d6102dd366004611fba565b6109bc565b6102ea601281565b60405160ff90911681526020016101fb565b6101b061030a366004611ffb565b610a5c565b6102c160085481565b6102c160095481565b6102c161032f366004612034565b610afc565b6102c1610342366004612034565b60016020526000908152604090205481565b6102c1600a5481565b6102c161036b366004612034565b60036020526000908152604090205481565b61039061038b366004612034565b610e2f565b604080519283526020830191909152016101fb565b6101ee6040518060400160405280600581526020017f58532d563100000000000000000000000000000000000000000000000000000081525081565b61027d6103ef366004611f8e565b6111e8565b6102c16103e881565b6101b061040b366004612034565b6111f5565b6004546102a0906001600160a01b031681565b6006546102a0906001600160a01b031681565b6102c1610444366004611ffb565b600260209081526000928352604080842090915290825290205481565b6101b0611352565b600b546001146104c05760405162461bcd60e51b815260206004820152600660248201527f4c4f434b4544000000000000000000000000000000000000000000000000000060448201526064015b60405180910390fd5b6000600b55841515806104d35750600084115b61051f5760405162461bcd60e51b815260206004820152601a60248201527f494e53554646494349454e545f4f55545055545f414d4f554e5400000000000060448201526064016104b7565b60008061057b6007546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b5091509150816dffffffffffffffffffffffffffff16871080156105ae5750806dffffffffffffffffffffffffffff1686105b6105fa5760405162461bcd60e51b815260206004820152601660248201527f494e53554646494349454e545f4c49515549444954590000000000000000000060448201526064016104b7565b60055460065460009182916001600160a01b039182169190811690891682148015906106385750806001600160a01b0316896001600160a01b031614155b6106845760405162461bcd60e51b815260206004820152600a60248201527f494e56414c49445f544f0000000000000000000000000000000000000000000060448201526064016104b7565b8a1561069557610695828a8d6114b8565b89156106a6576106a6818a8c6114b8565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa1580156106ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061070e9190612051565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015610755573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107799190612051565b92505050600089856dffffffffffffffffffffffffffff1661079b9190612099565b83116107a85760006107cc565b6107c28a6dffffffffffffffffffffffffffff8716612099565b6107cc9084612099565b905060006107ea8a6dffffffffffffffffffffffffffff8716612099565b83116107f757600061081b565b6108118a6dffffffffffffffffffffffffffff8716612099565b61081b9084612099565b9050600082118061082c5750600081115b6108785760405162461bcd60e51b815260206004820152601960248201527f494e53554646494349454e545f494e5055545f414d4f554e540000000000000060448201526064016104b7565b600061089a610888846003611631565b610894876103e8611631565b906116a1565b905060006108ac610888846003611631565b90506108d8620f42406108d26dffffffffffffffffffffffffffff8b8116908b16611631565b90611631565b6108e28383611631565b10156109305760405162461bcd60e51b815260206004820152600260248201527f204b00000000000000000000000000000000000000000000000000000000000060448201526064016104b7565b505061093e848488886116ff565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001600b55505050505050505050565b60006109b23384846119c1565b5060015b92915050565b6001600160a01b03831660009081526002602090815260408083203384529091528120546dffffffffffffffffffffffffffff14610a47576001600160a01b0384166000908152600260209081526040808320338452909152902054610a2290836116a1565b6001600160a01b03851660009081526002602090815260408083203384529091529020555b610a52848484611a23565b5060019392505050565b6004546001600160a01b03163314610ab65760405162461bcd60e51b815260206004820152600960248201527f464f5242494444454e000000000000000000000000000000000000000000000060448201526064016104b7565b600580546001600160a01b039384167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161790915560068054929093169116179055565b6000600b54600114610b505760405162461bcd60e51b815260206004820152600660248201527f4c4f434b4544000000000000000000000000000000000000000000000000000060448201526064016104b7565b6000600b819055600754600554604080516370a0823160e01b815230600482015290516dffffffffffffffffffffffffffff808516956e0100000000000000000000000000009095041693926001600160a01b0316916370a082319160248083019260209291908290030181865afa158015610bd0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bf49190612051565b6006546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015610c42573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c669190612051565b90506000610c84836dffffffffffffffffffffffffffff87166116a1565b90506000610ca2836dffffffffffffffffffffffffffff87166116a1565b90506000610cb08787611ac9565b60008054919250819003610cea57610cd66103e8610894610cd18787611631565b611c19565b9850610ce560006103e8611c89565b610d3f565b610d3c6dffffffffffffffffffffffffffff8916610d088684611631565b610d1291906120df565b6dffffffffffffffffffffffffffff8916610d2d8685611631565b610d3791906120df565b611d18565b98505b60008911610d8f5760405162461bcd60e51b815260206004820152601e60248201527f20494e53554646494349454e545f4c49515549444954595f4d494e544544000060448201526064016104b7565b610d998a8a611c89565b610da586868a8a6116ff565b8115610de157600754610ddd906dffffffffffffffffffffffffffff808216916e010000000000000000000000000000900416611631565b600a555b604080518581526020810185905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001600b5550949695505050505050565b600080600b54600114610e845760405162461bcd60e51b815260206004820152600660248201527f4c4f434b4544000000000000000000000000000000000000000000000000000060448201526064016104b7565b6000600b819055600754600554600654604080516370a0823160e01b815230600482015290516dffffffffffffffffffffffffffff808616966e01000000000000000000000000000090960416946001600160a01b0394851694909316929184916370a08231916024808201926020929091908290030181865afa158015610f10573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f349190612051565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa158015610f7e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fa29190612051565b30600090815260016020526040812054919250610fbf8888611ac9565b60005490915080610fd08487611631565b610fda91906120df565b9a5080610fe78486611631565b610ff191906120df565b995060008b118015611003575060008a115b61104f5760405162461bcd60e51b815260206004820152601d60248201527f494e53554646494349454e545f4c49515549444954595f4255524e454400000060448201526064016104b7565b6110593084611d30565b611064878d8d6114b8565b61106f868d8c6114b8565b6040516370a0823160e01b81523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa1580156110b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d79190612051565b6040516370a0823160e01b81523060048201529095506001600160a01b038716906370a0823190602401602060405180830381865afa15801561111e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111429190612051565b935061115085858b8b6116ff565b811561118c57600754611188906dffffffffffffffffffffffffffff808216916e010000000000000000000000000000900416611631565b600a555b604080518c8152602081018c90526001600160a01b038e169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050505050505050506001600b81905550915091565b60006109b2338484611a23565b600b546001146112475760405162461bcd60e51b815260206004820152600660248201527f4c4f434b4544000000000000000000000000000000000000000000000000000060448201526064016104b7565b6000600b556005546006546007546040516370a0823160e01b81523060048201526001600160a01b0393841693909216916112e991849186916112e4916dffffffffffffffffffffffffffff9091169084906370a08231906024015b602060405180830381865afa1580156112c0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108949190612051565b6114b8565b6007546040516370a0823160e01b815230600482015261134891839186916112e4916e0100000000000000000000000000009091046dffffffffffffffffffffffffffff16906001600160a01b038516906370a08231906024016112a3565b50506001600b5550565b600b546001146113a45760405162461bcd60e51b815260206004820152600660248201527f4c4f434b4544000000000000000000000000000000000000000000000000000060448201526064016104b7565b6000600b556005546040516370a0823160e01b81523060048201526114b1916001600160a01b0316906370a0823190602401602060405180830381865afa1580156113f3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114179190612051565b6006546040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa15801561145f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114839190612051565b6007546dffffffffffffffffffffffffffff808216916e0100000000000000000000000000009004166116ff565b6001600b55565b604080518082018252601981527f7472616e7366657228616464726573732c75696e74323536290000000000000060209182015281516001600160a01b0385811660248301526044808301869052845180840390910181526064909201845291810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839287169161157291906120f3565b6000604051808303816000865af19150503d80600081146115af576040519150601f19603f3d011682016040523d82523d6000602084013e6115b4565b606091505b50915091508180156115de5750805115806115de5750808060200190518101906115de919061210f565b61162a5760405162461bcd60e51b815260206004820152600f60248201527f5452414e534645525f4641494c4544000000000000000000000000000000000060448201526064016104b7565b5050505050565b6000811580611655575082826116478183612131565b925061165390836120df565b145b6109b65760405162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6d756c2d6f766572666c6f7700000000000000000000000060448201526064016104b7565b6000826116ae8382612099565b91508111156109b65760405162461bcd60e51b815260206004820152601560248201527f64732d6d6174682d7375622d756e646572666c6f77000000000000000000000060448201526064016104b7565b6dffffffffffffffffffffffffffff841115801561172b57506dffffffffffffffffffffffffffff8311155b6117775760405162461bcd60e51b815260206004820152600860248201527f4f564552464c4f5700000000000000000000000000000000000000000000000060448201526064016104b7565b60006117886401000000004261216e565b6007549091506000906117c1907c0100000000000000000000000000000000000000000000000000000000900463ffffffff1683612182565b905060008163ffffffff161180156117e857506dffffffffffffffffffffffffffff841615155b801561180357506dffffffffffffffffffffffffffff831615155b156118d1578063ffffffff166118408561181c86611dba565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690611de5565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166118689190612131565b6008600082825461187991906121a7565b909155505063ffffffff81166118928461181c87611dba565b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166118ba9190612131565b600960008282546118cb91906121a7565b90915550505b6007805463ffffffff84167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff8981166e0100000000000000000000000000009081027fffffffff000000000000000000000000000000000000000000000000000000009095168c83161794909417918216831794859055604080519382169282169290921783529290930490911660208201527f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a1505050505050565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038316600090815260016020526040902054611a4690826116a1565b6001600160a01b038085166000908152600160205260408082209390935590841681522054611a759082611e01565b6001600160a01b0380841660008181526001602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611a169085815260200190565b60048054604080517f017e7e58000000000000000000000000000000000000000000000000000000008152905160009384936001600160a01b03169263017e7e5892818301926020928290030181865afa158015611b2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b4f91906121bf565b600a546001600160a01b038216158015945091925090611c05578015611c00576000611b91610cd16dffffffffffffffffffffffffffff888116908816611631565b90506000611b9e83611c19565b905080821115611bfd576000611bc0611bb784846116a1565b60005490611631565b90506000611bd983611bd3866005611631565b90611e01565b90506000611be782846120df565b90508015611bf957611bf98782611c89565b5050505b50505b611c11565b8015611c11576000600a555b505092915050565b60006003821115611c7a5750806000611c336002836120df565b611c3e9060016121a7565b90505b81811015611c7457905080600281611c5981866120df565b611c6391906121a7565b611c6d91906120df565b9050611c41565b50919050565b8115611c84575060015b919050565b600054611c969082611e01565b60009081556001600160a01b038316815260016020526040902054611cbb9082611e01565b6001600160a01b0383166000818152600160205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611d0c9085815260200190565b60405180910390a35050565b6000818310611d275781611d29565b825b9392505050565b6001600160a01b038216600090815260016020526040902054611d5390826116a1565b6001600160a01b03831660009081526001602052604081209190915554611d7a90826116a1565b60009081556040518281526001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611d0c565b60006109b66e0100000000000000000000000000006dffffffffffffffffffffffffffff84166121dc565b6000611d296dffffffffffffffffffffffffffff831684612220565b600082611e0e83826121a7565b91508110156109b65760405162461bcd60e51b815260206004820152601460248201527f64732d6d6174682d6164642d6f766572666c6f7700000000000000000000000060448201526064016104b7565b6001600160a01b0381168114611e7457600080fd5b50565b600080600080600060808688031215611e8f57600080fd5b85359450602086013593506040860135611ea881611e5f565b9250606086013567ffffffffffffffff80821115611ec557600080fd5b818801915088601f830112611ed957600080fd5b813581811115611ee857600080fd5b896020828501011115611efa57600080fd5b9699959850939650602001949392505050565b60005b83811015611f28578181015183820152602001611f10565b83811115611f37576000848401525b50505050565b6020815260008251806020840152611f5c816040850160208701611f0d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008060408385031215611fa157600080fd5b8235611fac81611e5f565b946020939093013593505050565b600080600060608486031215611fcf57600080fd5b8335611fda81611e5f565b92506020840135611fea81611e5f565b929592945050506040919091013590565b6000806040838503121561200e57600080fd5b823561201981611e5f565b9150602083013561202981611e5f565b809150509250929050565b60006020828403121561204657600080fd5b8135611d2981611e5f565b60006020828403121561206357600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156120ab576120ab61206a565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000826120ee576120ee6120b0565b500490565b60008251612105818460208701611f0d565b9190910192915050565b60006020828403121561212157600080fd5b81518015158114611d2957600080fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156121695761216961206a565b500290565b60008261217d5761217d6120b0565b500690565b600063ffffffff8381169083168181101561219f5761219f61206a565b039392505050565b600082198211156121ba576121ba61206a565b500190565b6000602082840312156121d157600080fd5b8151611d2981611e5f565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff808316818516818304811182151516156122175761221761206a565b02949350505050565b60007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8084168061224f5761224f6120b0565b9216919091049291505056fea26469706673582212208f5e1f3ab66590215bedfca74b3a139254aed52eb2994dc46a64d6f64788e5e664736f6c634300080d0033a2646970667358221220dc3447b660f115ca2c41f1d62f090981fd42ebd2dec5567d9228e408a96d83eb64736f6c634300080d0033