Contract Address Details

0xC9567a8B6b622cdc8076C6b4432Ade0e11F50Da1

Contract Name
KaiDexFactory
Creator
0x0f5c21ā€“500dc9 at 0x86165eā€“1adaa8
Balance
0 KAI ( )
Tokens
Fetching tokens...
Transactions
5 Transactions
Transfers
0 Transfers
Gas Used
4,121,613
Last Balance Update
23345144
Contract name:
KaiDexFactory




Optimization enabled
true
Compiler version
v0.8.4+commit.c7e474f2




Optimization runs
200
EVM Version
default




Verified at
2022-07-12T10:32:17.293534Z

Constructor Arguments

0000000000000000000000000f5c21435895bb2f7044d0700281c05cbd500dc9

Arg [0] (address) : 0x0f5c21435895bb2f7044d0700281c05cbd500dc9

              

Contract source code

// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;

interface IKaiDexFactory {
    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;

}


// File contracts/exchange/interfaces/IKAIDexKRC20.sol

pragma solidity ^0.8.0;

interface IKAIDexKRC20 {
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Transfer(address indexed from, address indexed to, uint256 value);

    function name() external pure returns (string memory);

    function symbol() external pure returns (string memory);

    function decimals() external pure 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);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

    function nonces(address owner) external view returns (uint256);

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}


// File contracts/exchange/libraries/SafeMath.sol

pragma solidity ^0.8.0;

// 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");
    }
}


// File contracts/exchange/KAIDexKRC20.sol

pragma solidity ^0.8.0;


contract KAIDexKRC20 is IKAIDexKRC20 {
    using SafeMath for uint256;

    string public constant override name = "KAIDEX LPs";
    string public constant override symbol = "KDXLP";
    uint8 public constant override decimals = 18;
    uint256 public override totalSupply;
    mapping(address => uint256) public override balanceOf;
    mapping(address => mapping(address => uint256)) public override allowance;

    bytes32 public override DOMAIN_SEPARATOR;
    // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    bytes32 public constant override PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
    mapping(address => uint256) public override nonces;

    constructor() public {
        uint256 id;
        assembly {
            id := chainid()
        }
        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                keccak256(bytes(name)),
                keccak256(bytes("1")),
                id,
                address(this)
            )
        );
    }

    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) override external returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    function transfer(address to, uint256 value) override external returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) override external returns (bool) {
        if (allowance[from][msg.sender] != type(uint256).max) {
            allowance[from][msg.sender] = allowance[from][msg.sender].sub(value);
        }
        _transfer(from, to, value);
        return true;
    }

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) override external {
        require(deadline >= block.timestamp, "KAIDEX: EXPIRED");
        bytes32 digest = keccak256(
            abi.encodePacked(
                "\x19\x01",
                DOMAIN_SEPARATOR,
                keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
            )
        );
        address recoveredAddress = ecrecover(digest, v, r, s);
        require(recoveredAddress != address(0) && recoveredAddress == owner, "KAIDEX: INVALID_SIGNATURE");
        _approve(owner, spender, value);
    }
}


// File contracts/exchange/libraries/Math.sol

pragma solidity ^0.8.0;

// 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;
        }
    }
}


// File contracts/exchange/libraries/UQ112x112.sol

pragma solidity ^0.8.0;


// 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);
    }
}


// File contracts/exchange/interfaces/IKRC20.sol

pragma solidity ^0.8.0;

interface IKRC20 {
    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);
    
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}


// File contracts/exchange/interfaces/IKAIDexCallee.sol

pragma solidity ^0.8.0;

interface IKAIDexCallee {
    function KAIDexCall(address sender, uint amount0, uint amount1, bytes calldata data) external;
}


// File contracts/exchange/KaiDexPair.sol

pragma solidity ^0.8.0;






contract KaiDexPair is KAIDexKRC20 {
    using SafeMath  for uint;
    using UQ112x112 for uint224;

    uint 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

    uint public price0CumulativeLast;
    uint public price1CumulativeLast;
    uint public kLast; // reserve0 * reserve1, as of immediately after the most recent liquidity event

    uint private unlocked = 1;
    modifier lock() {
        require(unlocked == 1, 'KAIDEX: 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, uint value) private {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(SELECTOR, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'KAIDEX: TRANSFER_FAILED');
    }

    event Sync(uint112 reserve0, uint112 reserve1);
    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
    );

    constructor() public {
        factory = msg.sender;
    }

    // called once by the factory at time of deployment
    function initialize(address _token0, address _token1) external {
        require(msg.sender == factory, 'KAIDEX: FORBIDDEN'); // sufficient check
        token0 = _token0;
        token1 = _token1;
    }

    // update reserves and, on the first call per block, price accumulators
    function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
        require(balance0 <= type(uint112).max && balance1 <= type(uint112).max, 'KAIDEX: 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 += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
            price1CumulativeLast += uint(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 _mintFee(uint112 _reserve0, uint112 _reserve1) private returns (bool feeOn) {
        address feeTo = IKaiDexFactory(factory).feeTo();
        feeOn = feeTo != address(0);
        uint _kLast = kLast; // gas savings
        if (feeOn) {
            if (_kLast != 0) {
               uint rootK = Math.sqrt(uint(_reserve0).mul(_reserve1));
                uint rootKLast = Math.sqrt(_kLast);
                if (rootK > rootKLast) {
                    uint numerator = totalSupply.mul(rootK.sub(rootKLast));
                    uint denominator = rootK.mul(5).add(rootKLast);
                    uint 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 (uint liquidity) {
        (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
        uint balance0 = IKRC20(token0).balanceOf(address(this));
        uint balance1 = IKRC20(token1).balanceOf(address(this));
        uint amount0 = balance0.sub(_reserve0);
        uint amount1 = balance1.sub(_reserve1);
        bool feeOn = _mintFee(_reserve0, _reserve1);
        uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
        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, 'KAIDEX: INSUFFICIENT_LIQUIDITY_MINTED');
        _mint(to, liquidity);
        _update(balance0, balance1, _reserve0, _reserve1);
        if (feeOn) kLast = uint(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 (uint amount0, uint amount1) {
        (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
        address _token0 = token0;                                // gas savings
        address _token1 = token1;                                // gas savings
        uint balance0 = IKRC20(_token0).balanceOf(address(this));
        uint balance1 = IKRC20(_token1).balanceOf(address(this));
        uint liquidity = balanceOf[address(this)];

        bool feeOn = _mintFee(_reserve0, _reserve1);
        uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
        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, 'KAIDEX: INSUFFICIENT_LIQUIDITY_BURNED');
        _burn(address(this), liquidity);
        _safeTransfer(_token0, to, amount0);
        _safeTransfer(_token1, to, amount1);
        balance0 = IKRC20(_token0).balanceOf(address(this));
        balance1 = IKRC20(_token1).balanceOf(address(this));

        _update(balance0, balance1, _reserve0, _reserve1);
        if (feeOn) kLast = uint(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(uint amount0Out, uint amount1Out, address to, bytes calldata data) external lock {
        require(amount0Out > 0 || amount1Out > 0, 'KAIDEX: INSUFFICIENT_OUTPUT_AMOUNT');
        (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
        require(amount0Out < _reserve0 && amount1Out < _reserve1, 'KAIDEX: INSUFFICIENT_LIQUIDITY');

        uint balance0;
        uint balance1;
        { // scope for _token{0,1}, avoids stack too deep errors
        address _token0 = token0;
        address _token1 = token1;
        require(to != _token0 && to != _token1, 'KAIDEX: INVALID_TO');
        if (amount0Out > 0) _safeTransfer(_token0, to, amount0Out); // optimistically transfer tokens
        if (amount1Out > 0) _safeTransfer(_token1, to, amount1Out); // optimistically transfer tokens
        if (data.length > 0) IKAIDexCallee(to).KAIDexCall(msg.sender, amount0Out, amount1Out, data);
        balance0 = IKRC20(_token0).balanceOf(address(this));
        balance1 = IKRC20(_token1).balanceOf(address(this));
        }
        uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
        uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
        require(amount0In > 0 || amount1In > 0, 'KAIDexCall: INSUFFICIENT_INPUT_AMOUNT');
        { // scope for reserve{0,1}Adjusted, avoids stack too deep errors
            uint balance0Adjusted = balance0.mul(1000).sub(amount0In.mul(3));
            uint balance1Adjusted = balance1.mul(1000).sub(amount1In.mul(3));
            require(balance0Adjusted.mul(balance1Adjusted) >= uint(_reserve0).mul(_reserve1).mul(1000**2), 'KAIDexCall: 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, IKRC20(_token0).balanceOf(address(this)).sub(reserve0));
        _safeTransfer(_token1, to, IKRC20(_token1).balanceOf(address(this)).sub(reserve1));
    }

    // force reserves to match balances
    function sync() external lock {
        _update(IKRC20(token0).balanceOf(address(this)), IKRC20(token1).balanceOf(address(this)), reserve0, reserve1);
    }
}


// File contracts/exchange/Factory.sol

pragma solidity ^0.8.0;


contract KaiDexFactory is IKaiDexFactory {
    bytes32 public constant INIT_CODE_PAIR_HASH = keccak256(abi.encodePacked(type(KaiDexPair).creationCode));
    address public override feeTo;
    address public override feeToSetter;

    mapping(address => mapping(address => address)) public override getPair;
    address[] public override allPairs;

    constructor(address _feeToSetter) public {
        feeToSetter = _feeToSetter;
    }

    function allPairsLength() override external view returns (uint) {
        return allPairs.length;
    }

    function createPair(address tokenA, address tokenB) override external returns (address pair) {
        require(tokenA != tokenB, 'KAIDEX: IDENTICAL_ADDRESSES');
        (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        require(token0 != address(0), 'KAIDEX: ZERO_ADDRESS');
        require(getPair[token0][token1] == address(0), 'KAIDEX: PAIR_EXISTS'); // single check is sufficient
        bytes memory bytecode = type(KaiDexPair).creationCode;
        bytes32 salt = keccak256(abi.encodePacked(token0, token1));
        assembly {
            pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }
        KaiDexPair(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) override external {
        require(msg.sender == feeToSetter, 'KAIDEX: FORBIDDEN');
        feeTo = _feeTo;
    }

    function setFeeToSetter(address _feeToSetter) override external {
        require(msg.sender == feeToSetter, 'KAIDEX: FORBIDDEN');
        feeToSetter = _feeToSetter;
    }
}
        
>

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":"bytes32","name":"","internalType":"bytes32"}],"name":"INIT_CODE_PAIR_HASH","inputs":[]},{"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

0x608060405234801561001057600080fd5b50604051612b23380380612b2383398101604081905261002f91610054565b600180546001600160a01b0319166001600160a01b0392909216919091179055610082565b600060208284031215610065578081fd5b81516001600160a01b038116811461007b578182fd5b9392505050565b612a92806100916000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80635855a25a116100665780635855a25a14610100578063a2e74af614610108578063c9c653961461011d578063e6a4390514610130578063f46901ed1461016457600080fd5b8063017e7e5814610098578063094b7415146100c85780631e3dd18b146100db578063574f2ba3146100ee575b600080fd5b6000546100ab906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6001546100ab906001600160a01b031681565b6100ab6100e936600461063f565b610177565b6003545b6040519081526020016100bf565b6100f26101a1565b61011b6101163660046105ec565b6101eb565b005b6100ab61012b36600461060d565b610260565b6100ab61013e36600461060d565b60026020908152600092835260408084209091529082529020546001600160a01b031681565b61011b6101723660046105ec565b610553565b6003818154811061018757600080fd5b6000918252602090912001546001600160a01b0316905081565b6040516101b0602082016105c3565b601f1982820381018352601f9091011660408190526101d29190602001610657565b6040516020818303038152906040528051906020012081565b6001546001600160a01b0316331461023e5760405162461bcd60e51b815260206004820152601160248201527025a0a4a222ac1d102327a92124a22222a760791b60448201526064015b60405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000816001600160a01b0316836001600160a01b031614156102c45760405162461bcd60e51b815260206004820152601b60248201527f4b41494445583a204944454e544943414c5f41444452455353455300000000006044820152606401610235565b600080836001600160a01b0316856001600160a01b0316106102e75783856102ea565b84845b90925090506001600160a01b03821661033c5760405162461bcd60e51b81526020600482015260146024820152734b41494445583a205a45524f5f4144445245535360601b6044820152606401610235565b6001600160a01b038281166000908152600260209081526040808320858516845290915290205416156103a75760405162461bcd60e51b81526020600482015260136024820152724b41494445583a20504149525f45584953545360681b6044820152606401610235565b6000604051806020016103b9906105c3565b601f1982820381018352601f9091011660408190526bffffffffffffffffffffffff19606086811b8216602084015285901b166034820152909150600090604801604051602081830303815290604052805190602001209050808251602084016000f560405163485cc95560e01b81526001600160a01b03868116600483015285811660248301529196509086169063485cc95590604401600060405180830381600087803b15801561046b57600080fd5b505af115801561047f573d6000803e3d6000fd5b505050506001600160a01b0384811660008181526002602081815260408084208987168086529083528185208054978d166001600160a01b031998891681179091559383528185208686528352818520805488168517905560038054600181018255958190527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9095018054909716841790965592548351928352908201527f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9910160405180910390a35050505092915050565b6001546001600160a01b031633146105a15760405162461bcd60e51b815260206004820152601160248201527025a0a4a222ac1d102327a92124a22222a760791b6044820152606401610235565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6123cc8061069183390190565b80356001600160a01b03811681146105e757600080fd5b919050565b6000602082840312156105fd578081fd5b610606826105d0565b9392505050565b6000806040838503121561061f578081fd5b610628836105d0565b9150610636602084016105d0565b90509250929050565b600060208284031215610650578081fd5b5035919050565b60008251815b81811015610677576020818601810151858301520161065d565b818111156106855782828501525b50919091019291505056fe60806040526001600c5534801561001557600080fd5b50604080518082018252600a8152694b4149444558204c507360b01b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527f513da3f0e0fd390af3688dee67345fb74c26bc0c21a4e1c7dbf0223516ff33f4818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c09091019092528151910120600355600580546001600160a01b031916331790556122c4806101086000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c80636a627842116100f9578063ba9a7a5611610097578063d21220a711610071578063d21220a714610407578063d505accf1461041a578063dd62ed3e1461042d578063fff6cae91461045857600080fd5b8063ba9a7a56146103d8578063bc25cf77146103e1578063c45a0155146103f457600080fd5b80637ecebe00116100d35780637ecebe001461035957806389afcb441461037957806395d89b41146103a1578063a9059cbb146103c557600080fd5b80636a6278421461031d57806370a08231146103305780637464fc3d1461035057600080fd5b806323b872dd116101665780633644e515116101405780633644e515146102ef578063485cc955146102f85780635909c0d51461030b5780635a3d54931461031457600080fd5b806323b872dd1461029b57806330adf81f146102ae578063313ce567146102d557600080fd5b8063022c0d9f146101ae57806306fdde03146101c35780630902f1ac14610202578063095ea7b3146102365780630dfe16811461025957806318160ddd14610284575b600080fd5b6101c16101bc366004611fbb565b610460565b005b6101ec6040518060400160405280600a8152602001694b4149444558204c507360b01b81525081565b6040516101f991906120b4565b60405180910390f35b61020a610977565b604080516001600160701b03948516815293909216602084015263ffffffff16908201526060016101f9565b610249610244366004611f58565b6109a1565b60405190151581526020016101f9565b60065461026c906001600160a01b031681565b6040516001600160a01b0390911681526020016101f9565b61028d60005481565b6040519081526020016101f9565b6102496102a9366004611ea3565b6109b8565b61028d7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b6102dd601281565b60405160ff90911681526020016101f9565b61028d60035481565b6101c1610306366004611e6b565b610a4c565b61028d60095481565b61028d600a5481565b61028d61032b366004611e33565b610ac8565b61028d61033e366004611e33565b60016020526000908152604090205481565b61028d600b5481565b61028d610367366004611e33565b60046020526000908152604090205481565b61038c610387366004611e33565b610da8565b604080519283526020830191909152016101f9565b6101ec6040518060400160405280600581526020016404b44584c560dc1b81525081565b6102496103d3366004611f58565b611147565b61028d6103e881565b6101c16103ef366004611e33565b611154565b60055461026c906001600160a01b031681565b60075461026c906001600160a01b031681565b6101c1610428366004611ee3565b611277565b61028d61043b366004611e6b565b600260209081526000928352604080842090915290825290205481565b6101c1611488565b600c5460011461048b5760405162461bcd60e51b8152600401610482906120e7565b60405180910390fd5b6000600c558415158061049e5750600084115b6104f55760405162461bcd60e51b815260206004820152602260248201527f4b41494445583a20494e53554646494349454e545f4f55545055545f414d4f55604482015261139560f21b6064820152608401610482565b600080610500610977565b5091509150816001600160701b0316871080156105255750806001600160701b031686105b6105715760405162461bcd60e51b815260206004820152601e60248201527f4b41494445583a20494e53554646494349454e545f4c495155494449545900006044820152606401610482565b60065460075460009182916001600160a01b039182169190811690891682148015906105af5750806001600160a01b0316896001600160a01b031614155b6105f05760405162461bcd60e51b81526020600482015260126024820152714b41494445583a20494e56414c49445f544f60701b6044820152606401610482565b8a1561060157610601828a8d6115ca565b891561061257610612818a8c6115ca565b861561067f576040516303468d3b60e51b81526001600160a01b038a16906368d1a7609061064c9033908f908f908e908e90600401612068565b600060405180830381600087803b15801561066657600080fd5b505af115801561067a573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b1580156106be57600080fd5b505afa1580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190611fa3565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a082319060240160206040518083038186803b15801561073857600080fd5b505afa15801561074c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107709190611fa3565b92505050600089856001600160701b031661078b91906121af565b83116107985760006107b5565b6107ab8a6001600160701b0387166121af565b6107b590846121af565b905060006107cc8a6001600160701b0387166121af565b83116107d95760006107f6565b6107ec8a6001600160701b0387166121af565b6107f690846121af565b905060008211806108075750600081115b6108615760405162461bcd60e51b815260206004820152602560248201527f4b414944657843616c6c3a20494e53554646494349454e545f494e5055545f416044820152641353d5539560da1b6064820152608401610482565b6000610883610871846003611715565b61087d876103e8611715565b9061177c565b90506000610895610871846003611715565b90506108ba620f42406108b46001600160701b038b8116908b16611715565b90611715565b6108c48383611715565b10156109025760405162461bcd60e51b815260206004820152600d60248201526c4b414944657843616c6c3a204b60981b6044820152606401610482565b5050610910848488886117d2565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001600c55505050505050505050565b6008546001600160701b0380821692600160701b830490911691600160e01b900463ffffffff1690565b60006109ae3384846119bb565b5060015b92915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001914610a37576001600160a01b0384166000908152600260209081526040808320338452909152902054610a12908361177c565b6001600160a01b03851660009081526002602090815260408083203384529091529020555b610a42848484611a1d565b5060019392505050565b6005546001600160a01b03163314610a9a5760405162461bcd60e51b815260206004820152601160248201527025a0a4a222ac1d102327a92124a22222a760791b6044820152606401610482565b600680546001600160a01b039384166001600160a01b03199182161790915560078054929093169116179055565b6000600c54600114610aec5760405162461bcd60e51b8152600401610482906120e7565b6000600c81905580610afc610977565b506006546040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015610b4957600080fd5b505afa158015610b5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b819190611fa3565b6007546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015610bca57600080fd5b505afa158015610bde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c029190611fa3565b90506000610c19836001600160701b03871661177c565b90506000610c30836001600160701b03871661177c565b90506000610c3e8787611ac3565b60005490915080610c7557610c616103e861087d610c5c8787611715565b611c0f565b9850610c7060006103e8611c7f565b610cbc565b610cb96001600160701b038916610c8c8684611715565b610c96919061214d565b6001600160701b038916610caa8685611715565b610cb4919061214d565b611d0e565b98505b60008911610d1a5760405162461bcd60e51b815260206004820152602560248201527f4b41494445583a20494e53554646494349454e545f4c49515549444954595f4d604482015264125395115160da1b6064820152608401610482565b610d248a8a611c7f565b610d3086868a8a6117d2565b8115610d5a57600854610d56906001600160701b0380821691600160701b900416611715565b600b555b604080518581526020810185905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001600c5550949695505050505050565b600080600c54600114610dcd5760405162461bcd60e51b8152600401610482906120e7565b6000600c81905580610ddd610977565b506006546007546040516370a0823160e01b81523060048201529395509193506001600160a01b039081169291169060009083906370a082319060240160206040518083038186803b158015610e3257600080fd5b505afa158015610e46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6a9190611fa3565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a082319060240160206040518083038186803b158015610eaf57600080fd5b505afa158015610ec3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee79190611fa3565b30600090815260016020526040812054919250610f048888611ac3565b60005490915080610f158487611715565b610f1f919061214d565b9a5080610f2c8486611715565b610f36919061214d565b995060008b118015610f48575060008a115b610fa25760405162461bcd60e51b815260206004820152602560248201527f4b41494445583a20494e53554646494349454e545f4c49515549444954595f42604482015264155493915160da1b6064820152608401610482565b610fac3084611d26565b610fb7878d8d6115ca565b610fc2868d8c6115ca565b6040516370a0823160e01b81523060048201526001600160a01b038816906370a082319060240160206040518083038186803b15801561100157600080fd5b505afa158015611015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110399190611fa3565b6040516370a0823160e01b81523060048201529095506001600160a01b038716906370a082319060240160206040518083038186803b15801561107b57600080fd5b505afa15801561108f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b39190611fa3565b93506110c185858b8b6117d2565b81156110eb576008546110e7906001600160701b0380821691600160701b900416611715565b600b555b604080518c8152602081018c90526001600160a01b038e169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050505050505050506001600c81905550915091565b60006109ae338484611a1d565b600c546001146111765760405162461bcd60e51b8152600401610482906120e7565b6000600c556006546007546008546040516370a0823160e01b81523060048201526001600160a01b039384169390921691611220918491869161121b916001600160701b039091169084906370a08231906024015b60206040518083038186803b1580156111e357600080fd5b505afa1580156111f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087d9190611fa3565b6115ca565b6008546040516370a0823160e01b815230600482015261126d918391869161121b91600160701b9091046001600160701b0316906001600160a01b038516906370a08231906024016111cb565b50506001600c5550565b428410156112b95760405162461bcd60e51b815260206004820152600f60248201526e12d0525111560e8811561412549151608a1b6044820152606401610482565b6003546001600160a01b038816600090815260046020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b91908761130c8361221b565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012060405160200161138592919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa1580156113f0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906114265750886001600160a01b0316816001600160a01b0316145b6114725760405162461bcd60e51b815260206004820152601960248201527f4b41494445583a20494e56414c49445f5349474e4154555245000000000000006044820152606401610482565b61147d8989896119bb565b505050505050505050565b600c546001146114aa5760405162461bcd60e51b8152600401610482906120e7565b6000600c556006546040516370a0823160e01b81523060048201526115c3916001600160a01b0316906370a082319060240160206040518083038186803b1580156114f457600080fd5b505afa158015611508573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152c9190611fa3565b6007546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561156f57600080fd5b505afa158015611583573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a79190611fa3565b6008546001600160701b0380821691600160701b9004166117d2565b6001600c55565b604080518082018252601981527f7472616e7366657228616464726573732c75696e74323536290000000000000060209182015281516001600160a01b0385811660248301526044808301869052845180840390910181526064909201845291810180516001600160e01b031663a9059cbb60e01b17905291516000928392871691611656919061204c565b6000604051808303816000865af19150503d8060008114611693576040519150601f19603f3d011682016040523d82523d6000602084013e611698565b606091505b50915091508180156116c25750805115806116c25750808060200190518101906116c29190611f83565b61170e5760405162461bcd60e51b815260206004820152601760248201527f4b41494445583a205452414e534645525f4641494c45440000000000000000006044820152606401610482565b5050505050565b60008115806117395750828261172b8183612190565b9250611737908361214d565b145b6109b25760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b6044820152606401610482565b60008261178983826121af565b91508111156109b25760405162461bcd60e51b815260206004820152601560248201527464732d6d6174682d7375622d756e646572666c6f7760581b6044820152606401610482565b6001600160701b0384118015906117f057506001600160701b038311155b61182f5760405162461bcd60e51b815260206004820152601060248201526f4b41494445583a204f564552464c4f5760801b6044820152606401610482565b600061184064010000000042612236565b60085490915060009061186090600160e01b900463ffffffff16836121c6565b905060008163ffffffff1611801561188057506001600160701b03841615155b801561189457506001600160701b03831615155b15611923578063ffffffff166118bc856118ad86611db0565b6001600160e01b031690611dc9565b6001600160e01b03166118cf9190612190565b600960008282546118e0919061210f565b909155505063ffffffff81166118f9846118ad87611db0565b6001600160e01b031661190c9190612190565b600a600082825461191d919061210f565b90915550505b6008805463ffffffff8416600160e01b026001600160e01b036001600160701b03898116600160701b9081026001600160e01b03199095168c83161794909417918216831794859055604080519382169282169290921783529290930490911660208201527f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a1505050505050565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038316600090815260016020526040902054611a40908261177c565b6001600160a01b038085166000908152600160205260408082209390935590841681522054611a6f9082611dde565b6001600160a01b0380841660008181526001602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611a109085815260200190565b600080600560009054906101000a90046001600160a01b03166001600160a01b031663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b158015611b1457600080fd5b505afa158015611b28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b4c9190611e4f565b600b546001600160a01b038216158015945091925090611bfb578015611bf6576000611b87610c5c6001600160701b03888116908816611715565b90506000611b9483611c0f565b905080821115611bf3576000611bb6611bad848461177c565b60005490611715565b90506000611bcf83611bc9866005611715565b90611dde565b90506000611bdd828461214d565b90508015611bef57611bef8782611c7f565b5050505b50505b611c07565b8015611c07576000600b555b505092915050565b60006003821115611c705750806000611c2960028361214d565b611c3490600161210f565b90505b81811015611c6a57905080600281611c4f818661214d565b611c59919061210f565b611c63919061214d565b9050611c37565b50919050565b8115611c7a575060015b919050565b600054611c8c9082611dde565b60009081556001600160a01b038316815260016020526040902054611cb19082611dde565b6001600160a01b0383166000818152600160205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611d029085815260200190565b60405180910390a35050565b6000818310611d1d5781611d1f565b825b9392505050565b6001600160a01b038216600090815260016020526040902054611d49908261177c565b6001600160a01b03831660009081526001602052604081209190915554611d70908261177c565b60009081556040518281526001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611d02565b60006109b2600160701b6001600160701b038416612161565b6000611d1f6001600160701b03831684612127565b600082611deb838261210f565b91508110156109b25760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b6044820152606401610482565b600060208284031215611e44578081fd5b8135611d1f81612276565b600060208284031215611e60578081fd5b8151611d1f81612276565b60008060408385031215611e7d578081fd5b8235611e8881612276565b91506020830135611e9881612276565b809150509250929050565b600080600060608486031215611eb7578081fd5b8335611ec281612276565b92506020840135611ed281612276565b929592945050506040919091013590565b600080600080600080600060e0888a031215611efd578283fd5b8735611f0881612276565b96506020880135611f1881612276565b95506040880135945060608801359350608088013560ff81168114611f3b578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611f6a578182fd5b8235611f7581612276565b946020939093013593505050565b600060208284031215611f94578081fd5b81518015158114611d1f578182fd5b600060208284031215611fb4578081fd5b5051919050565b600080600080600060808688031215611fd2578081fd5b85359450602086013593506040860135611feb81612276565b9250606086013567ffffffffffffffff80821115612007578283fd5b818801915088601f83011261201a578283fd5b813581811115612028578384fd5b896020828501011115612039578384fd5b9699959850939650602001949392505050565b6000825161205e8184602087016121eb565b9190910192915050565b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60208152600082518060208401526120d38160408501602087016121eb565b601f01601f19169190910160400192915050565b6020808252600e908201526d12d0525111560e881313d0d2d15160921b604082015260600190565b600082198211156121225761212261224a565b500190565b60006001600160e01b038381168061214157612141612260565b92169190910492915050565b60008261215c5761215c612260565b500490565b60006001600160e01b03828116848216811515828404821116156121875761218761224a565b02949350505050565b60008160001904831182151516156121aa576121aa61224a565b500290565b6000828210156121c1576121c161224a565b500390565b600063ffffffff838116908316818110156121e3576121e361224a565b039392505050565b60005b838110156122065781810151838201526020016121ee565b83811115612215576000848401525b50505050565b600060001982141561222f5761222f61224a565b5060010190565b60008261224557612245612260565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b038116811461228b57600080fd5b5056fea264697066735822122002402f46a09feed7c0fcabe7f48a37e50b8ac31b1b916da406fbf1c1c05368c864736f6c63430008040033a264697066735822122073cc7aeae6505ce767fa22a6a210e910b16f2da2c73afb489e7c40b6a82d738664736f6c634300080400330000000000000000000000000f5c21435895bb2f7044d0700281c05cbd500dc9

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100935760003560e01c80635855a25a116100665780635855a25a14610100578063a2e74af614610108578063c9c653961461011d578063e6a4390514610130578063f46901ed1461016457600080fd5b8063017e7e5814610098578063094b7415146100c85780631e3dd18b146100db578063574f2ba3146100ee575b600080fd5b6000546100ab906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b6001546100ab906001600160a01b031681565b6100ab6100e936600461063f565b610177565b6003545b6040519081526020016100bf565b6100f26101a1565b61011b6101163660046105ec565b6101eb565b005b6100ab61012b36600461060d565b610260565b6100ab61013e36600461060d565b60026020908152600092835260408084209091529082529020546001600160a01b031681565b61011b6101723660046105ec565b610553565b6003818154811061018757600080fd5b6000918252602090912001546001600160a01b0316905081565b6040516101b0602082016105c3565b601f1982820381018352601f9091011660408190526101d29190602001610657565b6040516020818303038152906040528051906020012081565b6001546001600160a01b0316331461023e5760405162461bcd60e51b815260206004820152601160248201527025a0a4a222ac1d102327a92124a22222a760791b60448201526064015b60405180910390fd5b600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000816001600160a01b0316836001600160a01b031614156102c45760405162461bcd60e51b815260206004820152601b60248201527f4b41494445583a204944454e544943414c5f41444452455353455300000000006044820152606401610235565b600080836001600160a01b0316856001600160a01b0316106102e75783856102ea565b84845b90925090506001600160a01b03821661033c5760405162461bcd60e51b81526020600482015260146024820152734b41494445583a205a45524f5f4144445245535360601b6044820152606401610235565b6001600160a01b038281166000908152600260209081526040808320858516845290915290205416156103a75760405162461bcd60e51b81526020600482015260136024820152724b41494445583a20504149525f45584953545360681b6044820152606401610235565b6000604051806020016103b9906105c3565b601f1982820381018352601f9091011660408190526bffffffffffffffffffffffff19606086811b8216602084015285901b166034820152909150600090604801604051602081830303815290604052805190602001209050808251602084016000f560405163485cc95560e01b81526001600160a01b03868116600483015285811660248301529196509086169063485cc95590604401600060405180830381600087803b15801561046b57600080fd5b505af115801561047f573d6000803e3d6000fd5b505050506001600160a01b0384811660008181526002602081815260408084208987168086529083528185208054978d166001600160a01b031998891681179091559383528185208686528352818520805488168517905560038054600181018255958190527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b9095018054909716841790965592548351928352908201527f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9910160405180910390a35050505092915050565b6001546001600160a01b031633146105a15760405162461bcd60e51b815260206004820152601160248201527025a0a4a222ac1d102327a92124a22222a760791b6044820152606401610235565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b6123cc8061069183390190565b80356001600160a01b03811681146105e757600080fd5b919050565b6000602082840312156105fd578081fd5b610606826105d0565b9392505050565b6000806040838503121561061f578081fd5b610628836105d0565b9150610636602084016105d0565b90509250929050565b600060208284031215610650578081fd5b5035919050565b60008251815b81811015610677576020818601810151858301520161065d565b818111156106855782828501525b50919091019291505056fe60806040526001600c5534801561001557600080fd5b50604080518082018252600a8152694b4149444558204c507360b01b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527f513da3f0e0fd390af3688dee67345fb74c26bc0c21a4e1c7dbf0223516ff33f4818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c09091019092528151910120600355600580546001600160a01b031916331790556122c4806101086000396000f3fe608060405234801561001057600080fd5b50600436106101a95760003560e01c80636a627842116100f9578063ba9a7a5611610097578063d21220a711610071578063d21220a714610407578063d505accf1461041a578063dd62ed3e1461042d578063fff6cae91461045857600080fd5b8063ba9a7a56146103d8578063bc25cf77146103e1578063c45a0155146103f457600080fd5b80637ecebe00116100d35780637ecebe001461035957806389afcb441461037957806395d89b41146103a1578063a9059cbb146103c557600080fd5b80636a6278421461031d57806370a08231146103305780637464fc3d1461035057600080fd5b806323b872dd116101665780633644e515116101405780633644e515146102ef578063485cc955146102f85780635909c0d51461030b5780635a3d54931461031457600080fd5b806323b872dd1461029b57806330adf81f146102ae578063313ce567146102d557600080fd5b8063022c0d9f146101ae57806306fdde03146101c35780630902f1ac14610202578063095ea7b3146102365780630dfe16811461025957806318160ddd14610284575b600080fd5b6101c16101bc366004611fbb565b610460565b005b6101ec6040518060400160405280600a8152602001694b4149444558204c507360b01b81525081565b6040516101f991906120b4565b60405180910390f35b61020a610977565b604080516001600160701b03948516815293909216602084015263ffffffff16908201526060016101f9565b610249610244366004611f58565b6109a1565b60405190151581526020016101f9565b60065461026c906001600160a01b031681565b6040516001600160a01b0390911681526020016101f9565b61028d60005481565b6040519081526020016101f9565b6102496102a9366004611ea3565b6109b8565b61028d7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b6102dd601281565b60405160ff90911681526020016101f9565b61028d60035481565b6101c1610306366004611e6b565b610a4c565b61028d60095481565b61028d600a5481565b61028d61032b366004611e33565b610ac8565b61028d61033e366004611e33565b60016020526000908152604090205481565b61028d600b5481565b61028d610367366004611e33565b60046020526000908152604090205481565b61038c610387366004611e33565b610da8565b604080519283526020830191909152016101f9565b6101ec6040518060400160405280600581526020016404b44584c560dc1b81525081565b6102496103d3366004611f58565b611147565b61028d6103e881565b6101c16103ef366004611e33565b611154565b60055461026c906001600160a01b031681565b60075461026c906001600160a01b031681565b6101c1610428366004611ee3565b611277565b61028d61043b366004611e6b565b600260209081526000928352604080842090915290825290205481565b6101c1611488565b600c5460011461048b5760405162461bcd60e51b8152600401610482906120e7565b60405180910390fd5b6000600c558415158061049e5750600084115b6104f55760405162461bcd60e51b815260206004820152602260248201527f4b41494445583a20494e53554646494349454e545f4f55545055545f414d4f55604482015261139560f21b6064820152608401610482565b600080610500610977565b5091509150816001600160701b0316871080156105255750806001600160701b031686105b6105715760405162461bcd60e51b815260206004820152601e60248201527f4b41494445583a20494e53554646494349454e545f4c495155494449545900006044820152606401610482565b60065460075460009182916001600160a01b039182169190811690891682148015906105af5750806001600160a01b0316896001600160a01b031614155b6105f05760405162461bcd60e51b81526020600482015260126024820152714b41494445583a20494e56414c49445f544f60701b6044820152606401610482565b8a1561060157610601828a8d6115ca565b891561061257610612818a8c6115ca565b861561067f576040516303468d3b60e51b81526001600160a01b038a16906368d1a7609061064c9033908f908f908e908e90600401612068565b600060405180830381600087803b15801561066657600080fd5b505af115801561067a573d6000803e3d6000fd5b505050505b6040516370a0823160e01b81523060048201526001600160a01b038316906370a082319060240160206040518083038186803b1580156106be57600080fd5b505afa1580156106d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106f69190611fa3565b6040516370a0823160e01b81523060048201529094506001600160a01b038216906370a082319060240160206040518083038186803b15801561073857600080fd5b505afa15801561074c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107709190611fa3565b92505050600089856001600160701b031661078b91906121af565b83116107985760006107b5565b6107ab8a6001600160701b0387166121af565b6107b590846121af565b905060006107cc8a6001600160701b0387166121af565b83116107d95760006107f6565b6107ec8a6001600160701b0387166121af565b6107f690846121af565b905060008211806108075750600081115b6108615760405162461bcd60e51b815260206004820152602560248201527f4b414944657843616c6c3a20494e53554646494349454e545f494e5055545f416044820152641353d5539560da1b6064820152608401610482565b6000610883610871846003611715565b61087d876103e8611715565b9061177c565b90506000610895610871846003611715565b90506108ba620f42406108b46001600160701b038b8116908b16611715565b90611715565b6108c48383611715565b10156109025760405162461bcd60e51b815260206004820152600d60248201526c4b414944657843616c6c3a204b60981b6044820152606401610482565b5050610910848488886117d2565b60408051838152602081018390529081018c9052606081018b90526001600160a01b038a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350506001600c55505050505050505050565b6008546001600160701b0380821692600160701b830490911691600160e01b900463ffffffff1690565b60006109ae3384846119bb565b5060015b92915050565b6001600160a01b038316600090815260026020908152604080832033845290915281205460001914610a37576001600160a01b0384166000908152600260209081526040808320338452909152902054610a12908361177c565b6001600160a01b03851660009081526002602090815260408083203384529091529020555b610a42848484611a1d565b5060019392505050565b6005546001600160a01b03163314610a9a5760405162461bcd60e51b815260206004820152601160248201527025a0a4a222ac1d102327a92124a22222a760791b6044820152606401610482565b600680546001600160a01b039384166001600160a01b03199182161790915560078054929093169116179055565b6000600c54600114610aec5760405162461bcd60e51b8152600401610482906120e7565b6000600c81905580610afc610977565b506006546040516370a0823160e01b81523060048201529294509092506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015610b4957600080fd5b505afa158015610b5d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b819190611fa3565b6007546040516370a0823160e01b81523060048201529192506000916001600160a01b03909116906370a082319060240160206040518083038186803b158015610bca57600080fd5b505afa158015610bde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c029190611fa3565b90506000610c19836001600160701b03871661177c565b90506000610c30836001600160701b03871661177c565b90506000610c3e8787611ac3565b60005490915080610c7557610c616103e861087d610c5c8787611715565b611c0f565b9850610c7060006103e8611c7f565b610cbc565b610cb96001600160701b038916610c8c8684611715565b610c96919061214d565b6001600160701b038916610caa8685611715565b610cb4919061214d565b611d0e565b98505b60008911610d1a5760405162461bcd60e51b815260206004820152602560248201527f4b41494445583a20494e53554646494349454e545f4c49515549444954595f4d604482015264125395115160da1b6064820152608401610482565b610d248a8a611c7f565b610d3086868a8a6117d2565b8115610d5a57600854610d56906001600160701b0380821691600160701b900416611715565b600b555b604080518581526020810185905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a250506001600c5550949695505050505050565b600080600c54600114610dcd5760405162461bcd60e51b8152600401610482906120e7565b6000600c81905580610ddd610977565b506006546007546040516370a0823160e01b81523060048201529395509193506001600160a01b039081169291169060009083906370a082319060240160206040518083038186803b158015610e3257600080fd5b505afa158015610e46573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e6a9190611fa3565b6040516370a0823160e01b81523060048201529091506000906001600160a01b038416906370a082319060240160206040518083038186803b158015610eaf57600080fd5b505afa158015610ec3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ee79190611fa3565b30600090815260016020526040812054919250610f048888611ac3565b60005490915080610f158487611715565b610f1f919061214d565b9a5080610f2c8486611715565b610f36919061214d565b995060008b118015610f48575060008a115b610fa25760405162461bcd60e51b815260206004820152602560248201527f4b41494445583a20494e53554646494349454e545f4c49515549444954595f42604482015264155493915160da1b6064820152608401610482565b610fac3084611d26565b610fb7878d8d6115ca565b610fc2868d8c6115ca565b6040516370a0823160e01b81523060048201526001600160a01b038816906370a082319060240160206040518083038186803b15801561100157600080fd5b505afa158015611015573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110399190611fa3565b6040516370a0823160e01b81523060048201529095506001600160a01b038716906370a082319060240160206040518083038186803b15801561107b57600080fd5b505afa15801561108f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b39190611fa3565b93506110c185858b8b6117d2565b81156110eb576008546110e7906001600160701b0380821691600160701b900416611715565b600b555b604080518c8152602081018c90526001600160a01b038e169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050505050505050506001600c81905550915091565b60006109ae338484611a1d565b600c546001146111765760405162461bcd60e51b8152600401610482906120e7565b6000600c556006546007546008546040516370a0823160e01b81523060048201526001600160a01b039384169390921691611220918491869161121b916001600160701b039091169084906370a08231906024015b60206040518083038186803b1580156111e357600080fd5b505afa1580156111f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061087d9190611fa3565b6115ca565b6008546040516370a0823160e01b815230600482015261126d918391869161121b91600160701b9091046001600160701b0316906001600160a01b038516906370a08231906024016111cb565b50506001600c5550565b428410156112b95760405162461bcd60e51b815260206004820152600f60248201526e12d0525111560e8811561412549151608a1b6044820152606401610482565b6003546001600160a01b038816600090815260046020526040812080549192917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b91908761130c8361221b565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e0016040516020818303038152906040528051906020012060405160200161138592919061190160f01b81526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa1580156113f0573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906114265750886001600160a01b0316816001600160a01b0316145b6114725760405162461bcd60e51b815260206004820152601960248201527f4b41494445583a20494e56414c49445f5349474e4154555245000000000000006044820152606401610482565b61147d8989896119bb565b505050505050505050565b600c546001146114aa5760405162461bcd60e51b8152600401610482906120e7565b6000600c556006546040516370a0823160e01b81523060048201526115c3916001600160a01b0316906370a082319060240160206040518083038186803b1580156114f457600080fd5b505afa158015611508573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061152c9190611fa3565b6007546040516370a0823160e01b81523060048201526001600160a01b03909116906370a082319060240160206040518083038186803b15801561156f57600080fd5b505afa158015611583573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115a79190611fa3565b6008546001600160701b0380821691600160701b9004166117d2565b6001600c55565b604080518082018252601981527f7472616e7366657228616464726573732c75696e74323536290000000000000060209182015281516001600160a01b0385811660248301526044808301869052845180840390910181526064909201845291810180516001600160e01b031663a9059cbb60e01b17905291516000928392871691611656919061204c565b6000604051808303816000865af19150503d8060008114611693576040519150601f19603f3d011682016040523d82523d6000602084013e611698565b606091505b50915091508180156116c25750805115806116c25750808060200190518101906116c29190611f83565b61170e5760405162461bcd60e51b815260206004820152601760248201527f4b41494445583a205452414e534645525f4641494c45440000000000000000006044820152606401610482565b5050505050565b60008115806117395750828261172b8183612190565b9250611737908361214d565b145b6109b25760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6d756c2d6f766572666c6f7760601b6044820152606401610482565b60008261178983826121af565b91508111156109b25760405162461bcd60e51b815260206004820152601560248201527464732d6d6174682d7375622d756e646572666c6f7760581b6044820152606401610482565b6001600160701b0384118015906117f057506001600160701b038311155b61182f5760405162461bcd60e51b815260206004820152601060248201526f4b41494445583a204f564552464c4f5760801b6044820152606401610482565b600061184064010000000042612236565b60085490915060009061186090600160e01b900463ffffffff16836121c6565b905060008163ffffffff1611801561188057506001600160701b03841615155b801561189457506001600160701b03831615155b15611923578063ffffffff166118bc856118ad86611db0565b6001600160e01b031690611dc9565b6001600160e01b03166118cf9190612190565b600960008282546118e0919061210f565b909155505063ffffffff81166118f9846118ad87611db0565b6001600160e01b031661190c9190612190565b600a600082825461191d919061210f565b90915550505b6008805463ffffffff8416600160e01b026001600160e01b036001600160701b03898116600160701b9081026001600160e01b03199095168c83161794909417918216831794859055604080519382169282169290921783529290930490911660208201527f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a1505050505050565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b6001600160a01b038316600090815260016020526040902054611a40908261177c565b6001600160a01b038085166000908152600160205260408082209390935590841681522054611a6f9082611dde565b6001600160a01b0380841660008181526001602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611a109085815260200190565b600080600560009054906101000a90046001600160a01b03166001600160a01b031663017e7e586040518163ffffffff1660e01b815260040160206040518083038186803b158015611b1457600080fd5b505afa158015611b28573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b4c9190611e4f565b600b546001600160a01b038216158015945091925090611bfb578015611bf6576000611b87610c5c6001600160701b03888116908816611715565b90506000611b9483611c0f565b905080821115611bf3576000611bb6611bad848461177c565b60005490611715565b90506000611bcf83611bc9866005611715565b90611dde565b90506000611bdd828461214d565b90508015611bef57611bef8782611c7f565b5050505b50505b611c07565b8015611c07576000600b555b505092915050565b60006003821115611c705750806000611c2960028361214d565b611c3490600161210f565b90505b81811015611c6a57905080600281611c4f818661214d565b611c59919061210f565b611c63919061214d565b9050611c37565b50919050565b8115611c7a575060015b919050565b600054611c8c9082611dde565b60009081556001600160a01b038316815260016020526040902054611cb19082611dde565b6001600160a01b0383166000818152600160205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611d029085815260200190565b60405180910390a35050565b6000818310611d1d5781611d1f565b825b9392505050565b6001600160a01b038216600090815260016020526040902054611d49908261177c565b6001600160a01b03831660009081526001602052604081209190915554611d70908261177c565b60009081556040518281526001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611d02565b60006109b2600160701b6001600160701b038416612161565b6000611d1f6001600160701b03831684612127565b600082611deb838261210f565b91508110156109b25760405162461bcd60e51b815260206004820152601460248201527364732d6d6174682d6164642d6f766572666c6f7760601b6044820152606401610482565b600060208284031215611e44578081fd5b8135611d1f81612276565b600060208284031215611e60578081fd5b8151611d1f81612276565b60008060408385031215611e7d578081fd5b8235611e8881612276565b91506020830135611e9881612276565b809150509250929050565b600080600060608486031215611eb7578081fd5b8335611ec281612276565b92506020840135611ed281612276565b929592945050506040919091013590565b600080600080600080600060e0888a031215611efd578283fd5b8735611f0881612276565b96506020880135611f1881612276565b95506040880135945060608801359350608088013560ff81168114611f3b578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611f6a578182fd5b8235611f7581612276565b946020939093013593505050565b600060208284031215611f94578081fd5b81518015158114611d1f578182fd5b600060208284031215611fb4578081fd5b5051919050565b600080600080600060808688031215611fd2578081fd5b85359450602086013593506040860135611feb81612276565b9250606086013567ffffffffffffffff80821115612007578283fd5b818801915088601f83011261201a578283fd5b813581811115612028578384fd5b896020828501011115612039578384fd5b9699959850939650602001949392505050565b6000825161205e8184602087016121eb565b9190910192915050565b60018060a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b60208152600082518060208401526120d38160408501602087016121eb565b601f01601f19169190910160400192915050565b6020808252600e908201526d12d0525111560e881313d0d2d15160921b604082015260600190565b600082198211156121225761212261224a565b500190565b60006001600160e01b038381168061214157612141612260565b92169190910492915050565b60008261215c5761215c612260565b500490565b60006001600160e01b03828116848216811515828404821116156121875761218761224a565b02949350505050565b60008160001904831182151516156121aa576121aa61224a565b500290565b6000828210156121c1576121c161224a565b500390565b600063ffffffff838116908316818110156121e3576121e361224a565b039392505050565b60005b838110156122065781810151838201526020016121ee565b83811115612215576000848401525b50505050565b600060001982141561222f5761222f61224a565b5060010190565b60008261224557612245612260565b500690565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052601260045260246000fd5b6001600160a01b038116811461228b57600080fd5b5056fea264697066735822122002402f46a09feed7c0fcabe7f48a37e50b8ac31b1b916da406fbf1c1c05368c864736f6c63430008040033a264697066735822122073cc7aeae6505ce767fa22a6a210e910b16f2da2c73afb489e7c40b6a82d738664736f6c63430008040033