false
false
0

Contract Address Details

0xC1EdDCb8A8C5e5d6809D06C304BfBa99FAa16574

Contract Name
BlazeSwapFactory
Creator
0xea7316–df5143 at 0x78a856–6d3582
Balance
0 FLR
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
24200146
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
BlazeSwapFactory




Optimization enabled
true
Compiler version
v0.8.17+commit.8df45f5f




Optimization runs
10000
Verified at
2023-01-09T13:55:58.291730Z

Constructor Arguments

000000000000000000000000e007fd6bcbf3474a186b66bbe8ad1c373b86bc6b

Arg [0] (address) : 0xe007fd6bcbf3474a186b66bbe8ad1c373b86bc6b

              

contracts/core/BlazeSwapFactory.sol

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

import './interfaces/IBlazeSwapFactory.sol';
import './BlazeSwapBaseFactory.sol';
import './BlazeSwapPair.sol';

contract BlazeSwapFactory is IBlazeSwapFactory, BlazeSwapBaseFactory {
    mapping(address => bool) public isFlareAssetPairWithoutPlugin;

    constructor(address _manager) BlazeSwapBaseFactory(_manager) {}

    function pairCreationCode() internal pure virtual override returns (bytes memory code) {
        code = type(BlazeSwapPair).creationCode;
    }

    function initializePair(address pair, address token0, address token1) internal virtual override {
        super.initializePair(pair, token0, token1);
        IBlazeSwapManager m = IBlazeSwapManager(manager);
        BlazeSwapPair p = BlazeSwapPair(payable(pair));
        TokenType type0 = m.getTokenType(token0);
        TokenType type1 = m.getTokenType(token1);
        p.initialize(manager, token0, token1, type0, type1);
        if (type0 != TokenType.Generic || type1 != TokenType.Generic) {
            // the following code assumes that the delegation and ftsoRewards
            // plugins are available from the beginning
            p.addPlugin(m.delegationPlugin());
            if (type0 == TokenType.WNat || type1 == TokenType.WNat) {
                p.addPlugin(m.ftsoRewardPlugin());
                if (block.chainid == 14 || block.chainid == 114) {
                    p.addPlugin(m.airdropPlugin());
                }
            }
            if (type0 == TokenType.FlareAsset || type1 == TokenType.FlareAsset) {
                FlareAssetSupport flareAssetSupport = m.flareAssetSupport();
                if (flareAssetSupport == FlareAssetSupport.Full) {
                    p.addPlugin(m.flareAssetRewardPlugin());
                } else if (flareAssetSupport == FlareAssetSupport.Minimal) {
                    isFlareAssetPairWithoutPlugin[pair] = true;
                } else {
                    revert('BlazeSwap: FASSET_UNSUPPORTED');
                }
            }
        }
    }

    function upgradeFlareAssetPair(address pair) external {
        IBlazeSwapManager m = IBlazeSwapManager(manager);
        address plugin = m.flareAssetRewardPlugin();
        require(plugin != address(0) && isFlareAssetPairWithoutPlugin[pair], 'BlazeSwap: UPGRADE_NOT_NEEDED');
        isFlareAssetPairWithoutPlugin[pair] = false;
        BlazeSwapPair(payable(pair)).addPlugin(plugin);
    }
}
        

contracts/core/interfaces/IBlazeSwapManager.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;

import './flare/IFtsoRewardManager.sol';
import './IBlazeSwapBaseManager.sol';
import './Enumerations.sol';

interface IBlazeSwapManager is IBlazeSwapBaseManager {
    event AddFtsoRewardManager(address ftsoRewardManager);

    function updateFtsoRewardManagers(uint256 upTo) external;

    function getFtsoRewardManagers() external view returns (IFtsoRewardManager[] memory);

    function getActiveFtsoRewardManagers() external view returns (IFtsoRewardManager[] memory);

    function setRewardsFeeTo(address _rewardsFeeTo) external;

    function rewardsFeeTo() external view returns (address);

    function setFtsoRewardsFeeBips(uint256 _bips) external;

    function ftsoRewardsFeeBips() external view returns (uint256);

    function setFlareAssetRewardsFeeBips(uint256 _bips) external;

    function flareAssetRewardsFeeBips() external view returns (uint256);

    function setAirdropFeeBips(uint256 _bips) external;

    function airdropFeeBips() external view returns (uint256);

    function wNat() external view returns (address);

    function executorManager() external view returns (address);

    function getTokenType(address token) external view returns (TokenType tokenType);

    function delegationPlugin() external view returns (address);

    function ftsoRewardPlugin() external view returns (address);

    function airdropPlugin() external view returns (address);

    function flareAssetRewardPlugin() external view returns (address);

    function setFlareAssetRegistry(address _flareAssetRegistry) external;

    function flareAssetRegistry() external view returns (address registry);

    function setAllowFlareAssetPairsWithoutPlugin(bool _allowFlareAssetPairsWithoutPlugin) external;

    function allowFlareAssetPairsWithoutPlugin() external view returns (bool);

    function setDelegationPlugin(address _delegationPlugin) external;

    function setFtsoRewardPlugin(address _ftsoRewardPlugin) external;

    function setAirdropPlugin(address _airdropPlugin) external;

    function setFlareAssetsRewardPlugin(address _flareAssetRewardPlugin) external;

    function flareAssetSupport() external view returns (FlareAssetSupport);
}
          

contracts/core/interfaces/IBlazeSwapBaseManager.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;

import '../../shared/interfaces/IConfigurable.sol';

interface IBlazeSwapBaseManager is IConfigurable {
    function mathContext() external returns (address);

    function setTradingFeeTo(address _tradingFeeTo) external;

    function tradingFeeTo() external view returns (address);

    function setTradingFeeSplit(address router, address _recipient, uint256 _bips) external;

    function getTradingFeeSplit(address router) external view returns (address recipient, uint256 bips);
}
          

contracts/core/interfaces/erc20/IERC20Metadata.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IERC20Metadata {
    function name() external view returns (string memory);

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

    function decimals() external view returns (uint8);
}
          

contracts/core/interfaces/erc20/IERC20Snapshot.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IERC20Snapshot {
    function totalSupplyAt(uint256 block) external view returns (uint256);

    function balanceOfAt(address owner, uint256 block) external view returns (uint256);
}
          

contracts/core/interfaces/IBlazeSwapCallee.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IBlazeSwapCallee {
    function blazeSwapCall(address sender, uint256 amount0, uint256 amount1, bytes calldata data) external;
}
          

contracts/core/BlazeSwapMulticall.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import './interfaces/IBlazeSwapMulticall.sol';

import '../shared/libraries/DelegateCallHelper.sol';

abstract contract BlazeSwapMulticall is IBlazeSwapMulticall {
    function multicall(bytes[] calldata data) external returns (bytes[] memory results) {
        results = new bytes[](data.length);
        for (uint256 i; i < data.length; i++) {
            results[i] = DelegateCallHelper.delegateAndCheckResult(address(this), data[i]);
        }
    }
}
          

contracts/core/interfaces/IBlazeSwapPlugin.sol

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IBlazeSwapPlugin {
    function implementation() external view returns (address);
}
          

contracts/core/interfaces/IIBlazeSwapPluginImpl.sol

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.7.5;
pragma abicoder v2;

import './IBlazeSwapPluginImpl.sol';

interface IIBlazeSwapPluginImpl is IBlazeSwapPluginImpl {
    function initialize(address plugin) external;
}
          

contracts/core/interfaces/IBlazeSwapMulticall.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IBlazeSwapMulticall {
    function multicall(bytes[] calldata data) external returns (bytes[] memory results);
}
          

contracts/core/interfaces/flare/IWNat.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;

import '../erc20/IERC20.sol';
import '../erc20/IERC20Metadata.sol';
import '../erc20/IERC20Snapshot.sol';
import './IVPToken.sol';

interface IWNat is IERC20, IERC20Metadata, IERC20Snapshot, IVPToken {
    event Deposit(address indexed dst, uint256 amount);
    event Withdrawal(address indexed src, uint256 amount);

    function deposit() external payable;

    function depositTo(address recipient) external payable;

    function withdraw(uint256) external;

    function withdrawFrom(address owner, uint256 amount) external;
}
          

contracts/core/interfaces/eip2535/IDiamondCut.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

/******************************************************************************\
* Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/

interface IDiamondCut {
    enum FacetCutAction {
        Add,
        Replace,
        Remove
    }
    // Add=0, Replace=1, Remove=2

    struct FacetCut {
        address facetAddress;
        FacetCutAction action;
        bytes4[] functionSelectors;
    }

    event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);
}
          

contracts/shared/libraries/TransferHelper.sol

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

// helper methods for interacting with ERC20 tokens and sending NAT that do not consistently return true/false
library TransferHelper {
    function safeApprove(address token, address to, uint256 value) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeApprove');
    }

    function safeTransfer(address token, address to, uint256 value) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::safeTransfer');
    }

    function safeTransferFrom(address token, address from, address to, uint256 value) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper::transferFrom');
    }

    function safeTransferNAT(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, 'TransferHelper::safeTransferNAT');
    }
}
          

contracts/core/interfaces/flare/IPriceSubmitter.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IPriceSubmitter {
    function getFtsoManager() external view returns (address);
}
          

contracts/core/interfaces/IIBlazeSwapDelegation.sol

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.7.5;
pragma abicoder v2;

import './IIBlazeSwapPluginImpl.sol';

interface IIBlazeSwapDelegation is IIBlazeSwapPluginImpl {
    function transferDelegatorVotes(address from, address to, uint256 amount) external;

    function withdrawRewardFees(bool wrapped) external returns (uint256 rewardFees);
}
          

contracts/core/interfaces/IBlazeSwapBasePair.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;

import './erc20/IERC20.sol';
import './erc20/IERC20Metadata.sol';
import './erc20/IERC20Permit.sol';

interface IBlazeSwapBasePair is IERC20, IERC20Metadata, IERC20Permit {
    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);

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function factory() external view returns (address);

    function manager() external view returns (address);

    function token0() external view returns (address);

    function token1() external view returns (address);

    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);

    function price0CumulativeLast() external view returns (uint256);

    function price1CumulativeLast() external view returns (uint256);

    function kLast() external view returns (uint256);

    function mintFee() external;

    function mint(address to) external returns (uint256 liquidity);

    function burn(address to) external returns (uint256 amount0, uint256 amount1);

    function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;

    function splitFeeSwap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;

    function skim(address to) external;

    function sync() external;
}
          

contracts/core/interfaces/IBlazeSwapMath.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IBlazeSwapMath {
    function sqrt(uint256 x) external pure returns (uint256 r);

    function mulDiv(uint256 x, uint256 y, uint256 z) external pure returns (uint256 r);

    function mulDivRoundingUp(uint256 x, uint256 y, uint256 z) external pure returns (uint256 r);
}
          

contracts/core/interfaces/flare/IDistributionToDelegators.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IDistributionToDelegators {
    function votePowerBlockNumbers(uint256 _month) external view returns (uint256[] memory);

    function getClaimableAmount(uint256 _month) external view returns (uint256 _amountWei);

    function getClaimableAmountOf(address account, uint256 _month) external view returns (uint256 _amountWei);

    function claim(address payable _recipient, uint256 _month) external returns (uint256 _amountWei);

    function getCurrentMonth() external view returns (uint256 _currentMonth);

    function getMonthToExpireNext() external view returns (uint256 _monthToExpireNext);

    function secondsTillNextClaim() external view returns (uint256 _timetill);
}
          

contracts/core/interfaces/IBlazeSwapDelegation.sol

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IBlazeSwapDelegation {
    function voteOf(address liquidityProvider) external view returns (address);

    function providerVotes(address ftsoProvider) external view returns (uint256);

    function providers(uint256 index) external view returns (address);

    function providersCount() external view returns (uint256);

    function providersAll() external view returns (address[] memory);

    function providersSubset(uint256 offset, uint256 count) external view returns (address[] memory);

    function providersWithVotes() external view returns (address[] memory, uint256[] memory);

    function providersSubsetWithVotes(
        uint256 offset,
        uint256 count
    ) external view returns (address[] memory, uint256[] memory);

    function voteFor(address provider) external;

    function currentProviders() external view returns (address[] memory, uint256[] memory);

    function providersAtCurrentEpoch() external view returns (address[] memory, uint256[] memory);

    function providersAtEpoch(uint256 epoch) external view returns (address[] memory, uint256[] memory);

    function mostVotedProviders(uint256 max) external view returns (address[] memory, uint256[] memory);

    function changeProviders(address[] memory ftsoProviders) external;
}
          

contracts/core/interfaces/erc165/IERC165.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IERC165 {
    function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
          

contracts/core/interfaces/Enumerations.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;

enum TokenType {
    Generic,
    WNat,
    FlareAsset
}

enum FlareAssetSupport {
    None,
    Minimal,
    Full
}
          

contracts/core/interfaces/flare/IFtsoManager.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IFtsoManager {
    function rewardManager() external view returns (address);

    function getCurrentRewardEpoch() external view returns (uint256);

    function getRewardEpochVotePowerBlock(uint256 _rewardEpoch) external view returns (uint256);

    function getRewardEpochToExpireNext() external view returns (uint256); // not currently available on Songbird

    function rewardEpochDurationSeconds() external view returns (uint256);

    function rewardEpochs(
        uint256 _rewardEpochId
    ) external view returns (uint256 _votepowerBlock, uint256 _startBlock, uint256 _startTimestamp);
}
          

contracts/core/BlazeSwapERC20Snapshot.sol

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

import './BlazeSwapERC20.sol';
import './interfaces/erc20/IERC20Snapshot.sol';

contract BlazeSwapERC20Snapshot is BlazeSwapERC20, IERC20Snapshot {
    struct Snapshot {
        uint256 id;
        uint256 value;
    }
    mapping(address => Snapshot[]) private _accountBalanceSnapshots;
    Snapshot[] private _totalSupplySnapshots;
    uint256 private _currentSnapshotId;

    function _beforeTokenTransfer(address from, address to, uint256) internal virtual override {
        _updateSnapshot(from, to);
    }

    // ERC20 Snapshot extension allowing retrieval of historical balances and total supply,
    // inspired by https://github.com/Giveth/minime/blob/ea04d950eea153a04c51fa510b068b9dded390cb/contracts/MiniMeToken.sol[MiniMeToken]

    function _updateSnapshot(address from, address to) private {
        if (from == address(0)) {
            // mint
            _updateAccountSnapshot(to);
            _updateTotalSupplySnapshot();
        } else if (to == address(0)) {
            // burn
            _updateAccountSnapshot(from);
            _updateTotalSupplySnapshot();
        } else {
            // transfer
            _updateAccountSnapshot(from);
            _updateAccountSnapshot(to);
        }
    }

    function _updateAccountSnapshot(address account) private {
        _updateSnapshot(_accountBalanceSnapshots[account], balanceOf[account]);
    }

    function _updateTotalSupplySnapshot() private {
        _updateSnapshot(_totalSupplySnapshots, totalSupply);
    }

    function _updateSnapshot(Snapshot[] storage snapshots, uint256 currentValue) private {
        uint256 lastSnapshotId = (snapshots.length == 0) ? 0 : snapshots[snapshots.length - 1].id;
        if (lastSnapshotId < block.number) {
            Snapshot memory snapshot = Snapshot(block.number, currentValue);
            snapshots.push(snapshot);
        }
    }

    function _valueAt(uint256 snapshotId, Snapshot[] storage snapshots) private view returns (bool, uint256) {
        require(snapshotId <= block.number, 'BlazeSwap: INVALID_SNAPSHOT_ID');

        // find the first snapshots index with id > snapshotId in O(log(n))
        uint256 low;
        uint256 high = snapshots.length;
        while (low < high) {
            uint256 mid = (low + high) / 2; // overflow is not an issue in this case
            if (snapshots[mid].id > snapshotId) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }

        // if snapshotted, return the value
        return (low < snapshots.length) ? (true, snapshots[low].value) : (false, 0);
    }

    function balanceOfAt(address account, uint256 snapshotId) public view returns (uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _accountBalanceSnapshots[account]);
        return snapshotted ? value : balanceOf[account];
    }

    function totalSupplyAt(uint256 snapshotId) public view returns (uint256) {
        (bool snapshotted, uint256 value) = _valueAt(snapshotId, _totalSupplySnapshots);
        return snapshotted ? value : totalSupply;
    }
}
          

contracts/core/BlazeSwapPair.sol

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

import './BlazeSwapBasePair.sol';
import './BlazeSwapERC20Snapshot.sol';
import './BlazeSwapMulticall.sol';

import './interfaces/flare/IFtsoManager.sol';
import './interfaces/IBlazeSwapDelegation.sol';
import './interfaces/IBlazeSwapFactory.sol';
import './interfaces/IBlazeSwapManager.sol';
import './interfaces/IBlazeSwapPair.sol';
import './interfaces/IBlazeSwapPlugin.sol';
import './interfaces/IIBlazeSwapPluginImpl.sol';
import './interfaces/IIBlazeSwapDelegation.sol';

import './libraries/BlazeSwapFlareLibrary.sol';

library BlazeSwapPairStorage {
    struct Layout {
        address token0; // duplicated for easy/local access by plugins
        address token1; // duplicated for easy/local access by plugins
        TokenType type0;
        TokenType type1;
        mapping(bytes4 => bool) supportedInterfaces;
        mapping(bytes4 => address) pluginSelector;
        address[] pluginImpls; // first for delegation, others for rewards
    }

    bytes32 internal constant STORAGE_SLOT = keccak256('blazeswap.storage.BlazeSwapPair');

    function layout() internal pure returns (Layout storage l) {
        bytes32 slot = STORAGE_SLOT;
        assembly {
            l.slot := slot
        }
    }
}

contract BlazeSwapPair is IBlazeSwapPair, BlazeSwapBasePair, BlazeSwapERC20Snapshot, BlazeSwapMulticall {
    constructor() {
        BlazeSwapPairStorage.Layout storage l = BlazeSwapPairStorage.layout();
        l.supportedInterfaces[type(IDiamondLoupe).interfaceId] = true;
        l.supportedInterfaces[type(IERC165).interfaceId] = true;
        l.supportedInterfaces[type(IERC20).interfaceId] = true;
        l.supportedInterfaces[type(IERC20Metadata).interfaceId] = true;
        l.supportedInterfaces[type(IERC20Permit).interfaceId] = true;
        l.supportedInterfaces[type(IERC20Snapshot).interfaceId] = true;
        l.supportedInterfaces[type(IBlazeSwapMulticall).interfaceId] = true;
        l.supportedInterfaces[type(IBlazeSwapBasePair).interfaceId] = true;
        l.supportedInterfaces[type(IBlazeSwapPair).interfaceId] = true;
    }

    function initialize(
        address _manager,
        address _token0,
        address _token1,
        TokenType _type0,
        TokenType _type1
    ) external onlyParent {
        initialize(_manager, _token0, _token1);
        BlazeSwapPairStorage.Layout storage l = BlazeSwapPairStorage.layout();
        l.token0 = _token0;
        l.token1 = _token1;
        l.type0 = _type0;
        l.type1 = _type1;
    }

    function type0() external view returns (TokenType) {
        return BlazeSwapPairStorage.layout().type0;
    }

    function type1() external view returns (TokenType) {
        return BlazeSwapPairStorage.layout().type1;
    }

    function addPlugin(address plugin) external onlyParent {
        // the factory enforces that first plugin is for delegation, while next ones are for rewards
        address impl = IBlazeSwapPlugin(plugin).implementation();
        BlazeSwapPairStorage.Layout storage l = BlazeSwapPairStorage.layout();
        l.pluginImpls.push(impl);
        (bytes4[] memory selectors, bytes4 interfaceId) = IBlazeSwapPluginImpl(impl).pluginMetadata();
        for (uint256 i; i < selectors.length; i++) {
            require(l.pluginSelector[selectors[i]] == address(0));
            l.pluginSelector[selectors[i]] = impl;
        }
        FacetCut[] memory fc = new FacetCut[](1);
        fc[0] = FacetCut(impl, FacetCutAction.Add, selectors);
        bytes memory functionData = abi.encodeWithSelector(IIBlazeSwapPluginImpl.initialize.selector, plugin);
        emit DiamondCut(fc, impl, functionData);
        l.supportedInterfaces[interfaceId] = true;
        DelegateCallHelper.delegateAndCheckResult(impl, functionData);
    }

    // prettier-ignore
    fallback(bytes calldata _input) external returns (bytes memory result) {
        address plugin = BlazeSwapPairStorage.layout().pluginSelector[msg.sig];
        require(plugin != address(0), 'BlazeSwap: INVALID_FUNCTION');
        result = DelegateCallHelper.delegateAndCheckResult(plugin, _input);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 amount
    ) internal override(BlazeSwapERC20, BlazeSwapERC20Snapshot) {
        super._beforeTokenTransfer(from, to, amount);
        // move votes
        BlazeSwapPairStorage.Layout storage l = BlazeSwapPairStorage.layout();
        if (l.pluginImpls.length > 0) {
            address plugin = l.pluginImpls[0];
            DelegateCallHelper.delegateAndCheckResult(
                plugin,
                abi.encodeWithSelector(IIBlazeSwapDelegation.transferDelegatorVotes.selector, from, to, amount)
            );
        }
    }

    function supportsInterface(bytes4 interfaceID) external view returns (bool supported) {
        supported = BlazeSwapPairStorage.layout().supportedInterfaces[interfaceID];
    }

    function facets() external view returns (Facet[] memory facets_) {
        BlazeSwapPairStorage.Layout storage l = BlazeSwapPairStorage.layout();
        uint256 length = l.pluginImpls.length;
        facets_ = new Facet[](length);
        for (uint256 i; i < length; i++) {
            address plugin = l.pluginImpls[i];
            (bytes4[] memory selectors, ) = IBlazeSwapPluginImpl(plugin).pluginMetadata();
            facets_[i] = Facet(plugin, selectors);
        }
    }

    function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_) {
        BlazeSwapPairStorage.Layout storage l = BlazeSwapPairStorage.layout();
        uint256 length = l.pluginImpls.length;
        for (uint256 i; i < length; i++) {
            if (l.pluginImpls[i] == _facet) {
                (facetFunctionSelectors_, ) = IBlazeSwapPluginImpl(_facet).pluginMetadata();
                break;
            }
        }
    }

    function facetAddresses() external view returns (address[] memory facetAddresses_) {
        facetAddresses_ = BlazeSwapPairStorage.layout().pluginImpls;
    }

    function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_) {
        facetAddress_ = BlazeSwapPairStorage.layout().pluginSelector[_functionSelector];
    }
}
          

contracts/core/interfaces/erc20/IERC20Permit.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

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

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

    function DOMAIN_SEPARATOR() external view returns (bytes32);
}
          

contracts/core/libraries/BlazeSwapFlareLibrary.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import '../interfaces/flare/IDistributionTreasury.sol';
import '../interfaces/flare/IDistributionToDelegators.sol';
import '../interfaces/flare/IPriceSubmitter.sol';
import '../interfaces/flare/IFtsoManager.sol';
import '../interfaces/flare/IFtsoRewardManager.sol';
import '../interfaces/flare/IWNat.sol';

library BlazeSwapFlareLibrary {
    IPriceSubmitter private constant priceSubmitter = IPriceSubmitter(0x1000000000000000000000000000000000000003);
    IDistributionTreasury private constant distributionTreasury =
        IDistributionTreasury(0x1000000000000000000000000000000000000004);

    function getDistribution() internal view returns (IDistributionToDelegators distribution) {
        if (block.chainid == 14 || block.chainid == 114) {
            address curDistribution = distributionTreasury.selectedDistribution();
            if (curDistribution != address(0) && curDistribution == distributionTreasury.distributionToDelegators()) {
                distribution = IDistributionToDelegators(curDistribution);
            }
        }
    }

    function getFtsoManager() internal view returns (IFtsoManager) {
        return IFtsoManager(priceSubmitter.getFtsoManager());
    }

    function getFtsoRewardManager(IFtsoManager ftsoManager) internal view returns (IFtsoRewardManager) {
        return IFtsoRewardManager(ftsoManager.rewardManager());
    }

    function getWNat(IFtsoRewardManager ftsoRewardManager) internal view returns (IWNat) {
        return IWNat(ftsoRewardManager.wNat());
    }
}
          

contracts/core/interfaces/IBlazeSwapPair.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;

import './eip2535/IDiamondCut.sol';
import './eip2535/IDiamondLoupe.sol';
import './erc20/IERC20Snapshot.sol';
import './erc165/IERC165.sol';
import './IBlazeSwapBasePair.sol';
import './IBlazeSwapMulticall.sol';
import './Enumerations.sol';

interface IBlazeSwapPair is
    IBlazeSwapBasePair,
    IBlazeSwapMulticall,
    IERC20Snapshot,
    IERC165,
    IDiamondLoupe,
    IDiamondCut
{
    function type0() external view returns (TokenType);

    function type1() external view returns (TokenType);
}
          

contracts/core/interfaces/IBlazeSwapBaseFactory.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IBlazeSwapBaseFactory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint256 count);

    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 manager() external view returns (address);
}
          

contracts/core/interfaces/eip2535/IDiamondLoupe.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

/******************************************************************************\
* Author: Nick Mudge <[email protected]> (https://twitter.com/mudgen)
* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535
/******************************************************************************/

// A loupe is a small magnifying glass used to look at diamonds.
// These functions look at diamonds
interface IDiamondLoupe {
    /// These functions are expected to be called frequently
    /// by tools.

    struct Facet {
        address facetAddress;
        bytes4[] functionSelectors;
    }

    /// @notice Gets all facet addresses and their four byte function selectors.
    /// @return facets_ Facet
    function facets() external view returns (Facet[] memory facets_);

    /// @notice Gets all the function selectors supported by a specific facet.
    /// @param _facet The facet address.
    /// @return facetFunctionSelectors_
    function facetFunctionSelectors(address _facet) external view returns (bytes4[] memory facetFunctionSelectors_);

    /// @notice Get all the facet addresses used by a diamond.
    /// @return facetAddresses_
    function facetAddresses() external view returns (address[] memory facetAddresses_);

    /// @notice Gets the facet that supports the given selector.
    /// @dev If facet is not found return address(0).
    /// @param _functionSelector The function selector.
    /// @return facetAddress_ The facet address.
    function facetAddress(bytes4 _functionSelector) external view returns (address facetAddress_);
}
          

contracts/core/libraries/Math.sol

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

library Math {
    function min(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = x < y ? x : y;
    }
}
          

contracts/core/libraries/UQ112x112.sol

// SPDX-License-Identifier: GPL-3.0-or-later
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) {
        unchecked {
            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) {
        unchecked {
            z = x / uint224(y);
        }
    }
}
          

contracts/core/interfaces/flare/IDistributionTreasury.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IDistributionTreasury {
    function selectedDistribution() external view returns (address);

    function distributionToDelegators() external view returns (address);
}
          

contracts/core/interfaces/flare/IFtsoRewardManager.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IFtsoRewardManager {
    function active() external view returns (bool);

    function wNat() external view returns (address);

    function getRewardEpochToExpireNext() external view returns (uint256);

    function getEpochsWithUnclaimedRewards(address _beneficiary) external view returns (uint256[] memory _epochIds);

    function getStateOfRewards(
        address _beneficiary,
        uint256 _rewardEpoch
    )
        external
        view
        returns (
            address[] memory _dataProviders,
            uint256[] memory _rewardAmounts,
            bool[] memory _claimed,
            bool _claimable
        );

    function claimReward(
        address payable _recipient,
        uint256[] calldata _rewardEpochs
    ) external returns (uint256 _rewardAmount);

    function oldFtsoRewardManager() external view returns (address); // not currently available on Songbird

    function getUnclaimedReward(
        uint256 _rewardEpoch,
        address _dataProvider
    ) external view returns (uint256 _amount, uint256 _weight);

    function getDataProviderCurrentFeePercentage(address _dataProvider) external view returns (uint256);

    function getDataProviderScheduledFeePercentageChanges(
        address _dataProvider
    )
        external
        view
        returns (uint256[] memory _feePercentageBIPS, uint256[] memory _validFromEpoch, bool[] memory _fixed);
}
          

contracts/shared/interfaces/IConfigurable.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IConfigurable {
    function configSetter() external view returns (address);

    function setConfigSetter(address _configSetter) external;
}
          

contracts/core/interfaces/IBlazeSwapFactory.sol

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.7.5;
pragma abicoder v2;

import './IBlazeSwapBaseFactory.sol';

interface IBlazeSwapFactory is IBlazeSwapBaseFactory {
    function isFlareAssetPairWithoutPlugin(address pair) external view returns (bool);

    function upgradeFlareAssetPair(address pair) external;
}
          

contracts/core/BlazeSwapERC20.sol

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

import './interfaces/erc20/IERC20.sol';
import './interfaces/erc20/IERC20Metadata.sol';
import './interfaces/erc20/IERC20Permit.sol';

contract BlazeSwapERC20 is IERC20, IERC20Metadata, IERC20Permit {
    string public constant name = 'BlazeSwap';
    string public constant symbol = 'BLAZE-LP';
    uint8 public constant decimals = 18;
    uint256 public totalSupply;
    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;

    uint256 private immutable CACHED_CHAIN_ID;
    bytes32 private immutable CACHED_DOMAIN_SEPARATOR;

    bytes32 public constant PERMIT_TYPEHASH =
        keccak256('Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)');
    mapping(address => uint256) public nonces;

    constructor() {
        CACHED_CHAIN_ID = block.chainid;
        CACHED_DOMAIN_SEPARATOR = createDomainSeparator();
    }

    function createDomainSeparator() internal view returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
                    keccak256(bytes(name)),
                    keccak256(bytes('1')),
                    block.chainid,
                    address(this)
                )
            );
    }

    function DOMAIN_SEPARATOR() public view returns (bytes32) {
        return (CACHED_CHAIN_ID == block.chainid) ? CACHED_DOMAIN_SEPARATOR : createDomainSeparator();
    }

    function _beforeTokenTransfer(address from, address to, uint256 value) internal virtual {}

    function _mint(address to, uint256 value) internal {
        _beforeTokenTransfer(address(0), to, value);
        totalSupply += value;
        balanceOf[to] += value;
        emit Transfer(address(0), to, value);
    }

    function _burn(address from, uint256 value) internal {
        _beforeTokenTransfer(from, address(0), value);
        balanceOf[from] -= value;
        totalSupply -= 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 {
        require(to != address(0), 'BlazeSwap: ZERO_ADDRESS');
        _beforeTokenTransfer(from, to, value);
        balanceOf[from] -= value;
        balanceOf[to] += 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] != type(uint256).max) {
            allowance[from][msg.sender] = allowance[from][msg.sender] - value;
        }
        _transfer(from, to, value);
        return true;
    }

    // ERC20 Permit extension allowing approvals to be made via signatures,
    // as defined in https://eips.ethereum.org/EIPS/eip-2612 [EIP-2612].

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        require(deadline >= block.timestamp, 'BlazeSwap: 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, 'BlazeSwap: INVALID_SIGNATURE');
        _approve(owner, spender, value);
    }
}
          

contracts/core/interfaces/IBlazeSwapPluginImpl.sol

// SPDX-License-Identifier: BUSL-1.1
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IBlazeSwapPluginImpl {
    function pluginMetadata() external pure returns (bytes4[] memory selectors, bytes4 interfaceId);
}
          

contracts/shared/ParentRelation.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library ParentRelationStorage {
    struct Layout {
        address parent;
    }

    bytes32 internal constant STORAGE_SLOT = keccak256('blazeswap.storage.ParentRelation');

    function layout() internal pure returns (Layout storage l) {
        bytes32 slot = STORAGE_SLOT;
        assembly {
            l.slot := slot
        }
    }
}

abstract contract ParentRelation {
    constructor() {
        initParentRelation(msg.sender);
    }

    function initParentRelation(address _parent) internal {
        ParentRelationStorage.layout().parent = _parent;
    }

    function checkParent() private view {
        require(ParentRelationStorage.layout().parent == msg.sender, 'ParentRelation: FORBIDDEN');
    }

    modifier onlyParent() {
        checkParent();
        _;
    }
}
          

contracts/core/interfaces/erc20/IERC20.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

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

    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/core/BlazeSwapBaseFactory.sol

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

import './interfaces/IBlazeSwapBaseFactory.sol';
import './BlazeSwapBasePair.sol';

contract BlazeSwapBaseFactory is IBlazeSwapBaseFactory {
    address public immutable manager;

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

    constructor(address _manager) {
        require(_manager != address(0), 'BlazeSwap: ZERO_ADDRESS');
        manager = _manager;
    }

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

    function pairCreationCode() internal pure virtual returns (bytes memory code) {
        code = type(BlazeSwapBasePair).creationCode;
    }

    function initializePair(address pair, address token0, address token1) internal virtual {
        BlazeSwapBasePair(pair).initialize(manager, token0, token1);
    }

    function createPair(address tokenA, address tokenB) external returns (address pair) {
        require(tokenA != tokenB, 'BlazeSwap: IDENTICAL_ADDRESSES');
        (address token0, address token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        require(token0 != address(0), 'BlazeSwap: ZERO_ADDRESS');
        require(getPair[token0][token1] == address(0), 'BlazeSwap: PAIR_EXISTS'); // single check is sufficient

        // this way to create a contract (instead of `new`) allows to use deterministic addresses
        bytes32 salt = keccak256(abi.encodePacked(token0, token1));
        bytes memory bytecode = pairCreationCode();
        assembly {
            pair := create2(0, add(bytecode, 32), mload(bytecode), salt)
        }
        initializePair(pair, 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);
    }
}
          

contracts/core/interfaces/flare/IVPToken.sol

// SPDX-License-Identifier: MIT
pragma solidity >=0.7.5;
pragma abicoder v2;

interface IVPToken {
    function delegatesOf(
        address _owner
    )
        external
        view
        returns (address[] memory _delegateAddresses, uint256[] memory _bips, uint256 _count, uint256 _delegationMode);

    function delegatesOfAt(
        address _who,
        uint256 _blockNumber
    )
        external
        view
        returns (address[] memory _delegateAddresses, uint256[] memory _bips, uint256 _count, uint256 _delegationMode);

    function delegate(address _to, uint256 _bips) external;

    function undelegateAll() external;

    function totalVotePowerAt(uint256 _blockNumber) external view returns (uint256);

    function batchVotePowerOfAt(
        address[] memory _owners,
        uint256 _blockNumber
    ) external view returns (uint256[] memory);
}
          

contracts/shared/ReentrancyLock.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library ReentrancyLockStorage {
    struct Layout {
        uint256 status;
    }

    bytes32 internal constant STORAGE_SLOT = keccak256('blazeswap.storage.ReentrancyLock');

    function layout() internal pure returns (Layout storage l) {
        bytes32 slot = STORAGE_SLOT;
        assembly {
            l.slot := slot
        }
    }
}

abstract contract ReentrancyLock {
    function initReentrancyLock() internal {
        ReentrancyLockStorage.layout().status = 1;
    }

    function internalLock() private {
        ReentrancyLockStorage.Layout storage l = ReentrancyLockStorage.layout();
        require(l.status != 2, 'ReentrancyLock: reentrant call');
        l.status = 2;
    }

    function internalUnlock() private {
        ReentrancyLockStorage.layout().status = 1;
    }

    modifier lock() {
        internalLock();
        _;
        internalUnlock();
    }
}
          

contracts/shared/libraries/DelegateCallHelper.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

library DelegateCallHelper {
    function delegateAndCheckResult(address recipient, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory result) = recipient.delegatecall(data);

        if (!success) {
            if (result.length == 0) revert('DelegateCallHelper: revert with no reason');
            assembly {
                let result_len := mload(result)
                revert(add(32, result), result_len)
            }
        }

        return result;
    }
}
          

contracts/core/BlazeSwapBasePair.sol

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

import '../shared/libraries/TransferHelper.sol';
import '../shared/ParentRelation.sol';
import '../shared/ReentrancyLock.sol';
import './interfaces/IBlazeSwapBasePair.sol';
import './interfaces/IBlazeSwapBaseManager.sol';
import './interfaces/IBlazeSwapCallee.sol';
import './interfaces/IBlazeSwapMath.sol';
import './libraries/Math.sol';
import './libraries/UQ112x112.sol';
import './BlazeSwapERC20.sol';

contract BlazeSwapBasePair is IBlazeSwapBasePair, BlazeSwapERC20, ReentrancyLock, ParentRelation {
    using UQ112x112 for uint224;
    using TransferHelper for address;

    uint256 public constant MINIMUM_LIQUIDITY = 10 ** 3;
    bytes4 private constant SELECTOR = bytes4(keccak256(bytes('transfer(address,uint256)')));

    IBlazeSwapMath mc;

    address public manager;
    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 public pendingFeeTotal;
    mapping(address => uint256) public pendingFeeShare;
    address[] private pendingFeeAccount;

    function getReserves() public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
        _reserve0 = reserve0;
        _reserve1 = reserve1;
        _blockTimestampLast = blockTimestampLast;
    }

    function factory() external view returns (address) {
        return ParentRelationStorage.layout().parent;
    }

    // called once by the factory at time of deployment
    function initialize(address _manager, address _token0, address _token1) public onlyParent {
        mc = IBlazeSwapMath(IBlazeSwapBaseManager(_manager).mathContext());
        manager = _manager;
        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 <= type(uint112).max && balance1 <= type(uint112).max, 'BlazeSwap: OVERFLOW');
        uint32 blockTimestamp;
        unchecked {
            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);
    }

    function _wipePendingFeeData() private {
        for (uint256 i = pendingFeeAccount.length; i > 0; i--) {
            address splitFeeRecipient = pendingFeeAccount[i - 1];
            pendingFeeShare[splitFeeRecipient] = 0;
            pendingFeeAccount.pop();
        }
        pendingFeeTotal = 0;
    }

    // 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 = IBlazeSwapBaseManager(manager).tradingFeeTo();
        feeOn = feeTo != address(0);
        uint256 _kLast = kLast; // gas savings
        if (feeOn) {
            if (_kLast != 0) {
                uint256 rootK = mc.sqrt(uint256(_reserve0) * _reserve1);
                uint256 rootKLast = mc.sqrt(_kLast);
                if (rootK > rootKLast) {
                    uint256 numerator = totalSupply * (rootK - rootKLast);
                    uint256 denominator = rootK * 5 + rootKLast;
                    uint256 liquidity = numerator / denominator;
                    if (liquidity > 0) {
                        for (uint256 i; i < pendingFeeAccount.length; i++) {
                            address splitFeeRecipient = pendingFeeAccount[i];
                            uint256 splitFeeLiquidity = mc.mulDiv(
                                liquidity,
                                pendingFeeShare[splitFeeRecipient],
                                pendingFeeTotal
                            );
                            if (splitFeeLiquidity > 0) {
                                _mint(splitFeeRecipient, splitFeeLiquidity);
                                liquidity -= splitFeeLiquidity;
                            }
                        }
                        if (liquidity > 0) {
                            _mint(feeTo, liquidity);
                        }
                    }
                }
                _wipePendingFeeData();
            }
        } else if (_kLast != 0) {
            kLast = 0;
            _wipePendingFeeData();
        }
    }

    function mintFee() external {
        (uint112 _reserve0, uint112 _reserve1, ) = getReserves(); // gas savings
        bool feeOn = _mintFee(_reserve0, _reserve1);
        if (feeOn) kLast = uint256(_reserve0) * _reserve1;
    }

    // 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 - _reserve0;
        uint256 amount1 = balance1 - _reserve1;

        bool feeOn = _mintFee(_reserve0, _reserve1);
        uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
        if (_totalSupply == 0) {
            liquidity = mc.sqrt(amount0 * amount1) - MINIMUM_LIQUIDITY;
            _mint(address(0x000000000000000000000000000000000000dEaD), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
        } else {
            liquidity = Math.min((amount0 * _totalSupply) / _reserve0, (amount1 * _totalSupply) / _reserve1);
        }
        require(liquidity > 0, 'BlazeSwap: INSUFFICIENT_LIQUIDITY_MINTED');
        _mint(to, liquidity);

        _update(balance0, balance1, _reserve0, _reserve1);
        unchecked {
            if (feeOn) kLast = uint256(reserve0) * 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 = _mintFee(_reserve0, _reserve1);
        uint256 _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
        amount0 = (liquidity * balance0) / _totalSupply; // using balances ensures pro-rata distribution
        amount1 = (liquidity * balance1) / _totalSupply; // using balances ensures pro-rata distribution
        require(amount0 > 0 && amount1 > 0, 'BlazeSwap: INSUFFICIENT_LIQUIDITY_BURNED');
        _burn(address(this), liquidity);
        _token0.safeTransfer(to, amount0);
        _token1.safeTransfer(to, amount1);
        balance0 = IERC20(_token0).balanceOf(address(this));
        balance1 = IERC20(_token1).balanceOf(address(this));

        _update(balance0, balance1, _reserve0, _reserve1);
        if (feeOn) kLast = uint256(reserve0) * reserve1; // reserve0 and reserve1 are up-to-date
        emit Burn(msg.sender, amount0, amount1, to);
    }

    function _recordSwapFees(uint112 oldReserve0, uint112 oldReserve1, bool splitFee) private {
        if (kLast != 0) {
            (uint112 newReserve0, uint112 newReserve1, ) = getReserves();
            uint256 feeShare = uint256(newReserve0) * newReserve1 - uint256(oldReserve0) * oldReserve1;
            pendingFeeTotal += feeShare;
            if (splitFee) {
                (address splitFeeRecipient, uint256 splitFeeBips) = IBlazeSwapBaseManager(manager).getTradingFeeSplit(
                    msg.sender
                );
                if (splitFeeRecipient != address(0) && splitFeeBips > 0) {
                    uint256 splitFeeShare = (feeShare * splitFeeBips) / 100_00;
                    if (feeShare > 0) {
                        uint256 oldFeeShare = pendingFeeShare[splitFeeRecipient];
                        if (oldFeeShare == 0) {
                            pendingFeeAccount.push(splitFeeRecipient);
                        }
                        pendingFeeShare[splitFeeRecipient] += splitFeeShare;
                    }
                }
            }
        }
    }

    function splitFeeSwap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external {
        (uint112 _reserve0, uint112 _reserve1, ) = getReserves();
        swapInternal(_reserve0, reserve1, amount0Out, amount1Out, to, data);
        _recordSwapFees(_reserve0, _reserve1, true);
    }

    function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external {
        (uint112 _reserve0, uint112 _reserve1, ) = getReserves();
        swapInternal(_reserve0, reserve1, amount0Out, amount1Out, to, data);
        _recordSwapFees(_reserve0, _reserve1, false);
    }

    // this low-level function should be called from a contract which performs important safety checks
    function swapInternal(
        uint112 _reserve0,
        uint112 _reserve1,
        uint256 amount0Out,
        uint256 amount1Out,
        address to,
        bytes calldata data
    ) internal lock {
        require(amount0Out > 0 || amount1Out > 0, 'BlazeSwap: INSUFFICIENT_OUTPUT_AMOUNT');
        require(amount0Out < _reserve0 && amount1Out < _reserve1, 'BlazeSwap: 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, 'BlazeSwap: INVALID_TO');
            if (amount0Out > 0) _token0.safeTransfer(to, amount0Out);
            // optimistically transfer tokens
            if (amount1Out > 0) _token1.safeTransfer(to, amount1Out);
            // optimistically transfer tokens
            if (data.length > 0) IBlazeSwapCallee(to).blazeSwapCall(msg.sender, amount0Out, amount1Out, data);
            balance0 = IERC20(_token0).balanceOf(address(this));
            balance1 = IERC20(_token1).balanceOf(address(this));
        }
        uint256 amount0In;
        uint256 amount1In;
        unchecked {
            amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
            amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
        }
        require(amount0In > 0 || amount1In > 0, 'BlazeSwap: INSUFFICIENT_INPUT_AMOUNT');
        {
            // scope for reserve{0,1}Adjusted, avoids stack too deep errors
            uint256 balance0Adjusted = balance0 * 1000 - amount0In * 3;
            uint256 balance1Adjusted = balance1 * 1000 - amount1In * 3;
            require(balance0Adjusted * balance1Adjusted >= uint256(_reserve0) * _reserve1 * 1000 ** 2, 'BlazeSwap: 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
        _token0.safeTransfer(to, IERC20(_token0).balanceOf(address(this)) - reserve0);
        _token1.safeTransfer(to, IERC20(_token1).balanceOf(address(this)) - reserve1);
    }

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

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_manager","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":"count","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":"getPair","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isFlareAssetPairWithoutPlugin","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"manager","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"upgradeFlareAssetPair","inputs":[{"type":"address","name":"pair","internalType":"address"}]}]
              

Contract Creation Code

0x60a060405234801561001057600080fd5b5060405161604138038061604183398101604081905261002f9161009c565b806001600160a01b03811661008a5760405162461bcd60e51b815260206004820152601760248201527f426c617a65537761703a205a45524f5f41444452455353000000000000000000604482015260640160405180910390fd5b6001600160a01b0316608052506100cc565b6000602082840312156100ae57600080fd5b81516001600160a01b03811681146100c557600080fd5b9392505050565b608051615f3f6101026000396000818160d3015281816101eb015281816108030152818161096001526110940152615f3f6000f3fe60806040523480156200001157600080fd5b5060043610620000875760003560e01c806364b3b82a116200006257806364b3b82a1462000107578063926d8c331462000120578063c9c653961462000157578063e6a43905146200016e57600080fd5b80631e3dd18b146200008c578063481c6a7514620000cd578063574f2ba314620000f5575b600080fd5b620000a36200009d366004620010ea565b620001af565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620000a37f000000000000000000000000000000000000000000000000000000000000000081565b600154604051908152602001620000c4565b6200011e620001183660046200112a565b620001e7565b005b62000146620001313660046200112a565b60026020526000908152604090205460ff1681565b6040519015158152602001620000c4565b620000a36200016836600462001151565b620003f7565b620000a36200017f36600462001151565b600060208181529281526040808220909352908152205473ffffffffffffffffffffffffffffffffffffffff1681565b60018181548110620001c057600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60007f0000000000000000000000000000000000000000000000000000000000000000905060008173ffffffffffffffffffffffffffffffffffffffff166309b58a656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200025a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200028091906200118f565b905073ffffffffffffffffffffffffffffffffffffffff811615801590620002cd575073ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604090205460ff165b62000339576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f426c617a65537761703a20555047524144455f4e4f545f4e454544454400000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8381166000818152600260205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517fd8867fc800000000000000000000000000000000000000000000000000000000815291831660048301529063d8867fc8906024015b600060405180830381600087803b158015620003d957600080fd5b505af1158015620003ee573d6000803e3d6000fd5b50505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f426c617a65537761703a204944454e544943414c5f4144445245535345530000604482015260640162000330565b6000808373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1610620004cf578385620004d2565b84845b909250905073ffffffffffffffffffffffffffffffffffffffff821662000556576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f426c617a65537761703a205a45524f5f41444452455353000000000000000000604482015260640162000330565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526020818152604080832085851684529091529020541615620005f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f426c617a65537761703a20504149525f45584953545300000000000000000000604482015260640162000330565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084811b8216602084015283901b16603482015260009060480160405160208183030381529060405280519060200120905060006200065562000767565b9050818151602083016000f5945062000670858585620007b1565b73ffffffffffffffffffffffffffffffffffffffff84811660008181526020818152604080832088861680855290835281842080547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116978d1697881790915584845282852086865284528285208054821688179055600180548082018255958190527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6909501805490911687179055925481519586529185019190915290927f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9910160405180910390a35050505092915050565b6060604051806020016200077b90620010dc565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052919050565b620007be83838362001057565b6040517f93272baf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f0000000000000000000000000000000000000000000000000000000000000000918591600091908416906393272baf90602401602060405180830381865afa15801562000853573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008799190620011bd565b6040517f93272baf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301529192506000918516906393272baf90602401602060405180830381865afa158015620008ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620009129190620011bd565b6040517f903cd3e300000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff84169063903cd3e39062000991907f0000000000000000000000000000000000000000000000000000000000000000908a908a908890889060040162001248565b600060405180830381600087803b158015620009ac57600080fd5b505af1158015620009c1573d6000803e3d6000fd5b5060009250620009cf915050565b826002811115620009e457620009e4620011dd565b14158062000a075750600081600281111562000a045762000a04620011dd565b14155b15620003ee578273ffffffffffffffffffffffffffffffffffffffff1663d8867fc88573ffffffffffffffffffffffffffffffffffffffff1663d68492106040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000a75573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a9b91906200118f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401600060405180830381600087803b15801562000b0257600080fd5b505af115801562000b17573d6000803e3d6000fd5b506001925062000b25915050565b82600281111562000b3a5762000b3a620011dd565b148062000b5b5750600181600281111562000b595762000b59620011dd565b145b1562000d94578273ffffffffffffffffffffffffffffffffffffffff1663d8867fc88573ffffffffffffffffffffffffffffffffffffffff1663e6030c5d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000bc9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000bef91906200118f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401600060405180830381600087803b15801562000c5657600080fd5b505af115801562000c6b573d6000803e3d6000fd5b5050505046600e148062000c7f5750466072145b1562000d94578273ffffffffffffffffffffffffffffffffffffffff1663d8867fc88573ffffffffffffffffffffffffffffffffffffffff1663d1f133b66040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000ced573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000d1391906200118f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401600060405180830381600087803b15801562000d7a57600080fd5b505af115801562000d8f573d6000803e3d6000fd5b505050505b600282600281111562000dab5762000dab620011dd565b148062000dcc5750600281600281111562000dca5762000dca620011dd565b145b15620003ee5760008473ffffffffffffffffffffffffffffffffffffffff16630d92c1ca6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000e20573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e469190620011bd565b9050600281600281111562000e5f5762000e5f620011dd565b0362000f79578373ffffffffffffffffffffffffffffffffffffffff1663d8867fc88673ffffffffffffffffffffffffffffffffffffffff166309b58a656040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000ecd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ef391906200118f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401600060405180830381600087803b15801562000f5a57600080fd5b505af115801562000f6f573d6000803e3d6000fd5b505050506200104d565b600181600281111562000f905762000f90620011dd565b0362000fea5773ffffffffffffffffffffffffffffffffffffffff8816600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556200104d565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f426c617a65537761703a204641535345545f554e535550504f52544544000000604482015260640162000330565b5050505050505050565b6040517fc0c53b8b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000811660048301528381166024830152828116604483015284169063c0c53b8b90606401620003be565b614c95806200129e83390190565b600060208284031215620010fd57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146200112757600080fd5b50565b6000602082840312156200113d57600080fd5b81356200114a8162001104565b9392505050565b600080604083850312156200116557600080fd5b8235620011728162001104565b91506020830135620011848162001104565b809150509250929050565b600060208284031215620011a257600080fd5b81516200114a8162001104565b600381106200112757600080fd5b600060208284031215620011d057600080fd5b81516200114a81620011af565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6003811062001244577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b73ffffffffffffffffffffffffffffffffffffffff868116825285811660208301528416604082015260a081016200128460608301856200120c565b6200129360808301846200120c565b969550505050505056fe60c06040523480156200001157600080fd5b5046608052620000ea60408051808201825260098152680426c617a65537761760bc1b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527f4f3c2418297976d44521b7127fe41c4e9949d309a364d0680ee7c3855be9a8b6818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c0909101909252815191012090565b60a052620000f833620001eb565b60006200010f6200022260201b620009821760201c565b6348e2b09360e01b600090815260029091016020526040808220805460ff1990811660019081179092556301ffc9a760e01b845282842080548216831790556336372b0760e01b8452828420805482168317905563a219a02560e01b84528284208054821683179055634ec7fbed60e11b84528284208054821683179055636b7cf4d760e11b84528284208054821683179055631592ca1b60e31b84528284208054821683179055636a865ca360e01b8452828420805482168317905563bc83a82960e01b84529190922080549091169091179055506200026a565b80620002016200024660201b6200277a1760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f2490565b7f52720094aed01ff34e348759e70383310167af8639ed3cc691bb00386db89cda90565b60805160a051614a05620002906000396000610dc901526000610ca10152614a056000f3fe608060405234801561001057600080fd5b50600436106102f45760003560e01c80637464fc3d11610191578063b41a06f3116100e3578063cdffacc611610097578063d8867fc811610071578063d8867fc81461093c578063dd62ed3e1461094f578063fff6cae91461097a576102f4565b8063cdffacc6146108ac578063d21220a714610916578063d505accf14610929576102f4565b8063bc25cf77116100c8578063bc25cf7714610856578063c0c53b8b14610869578063c45a01551461087c576102f4565b8063b41a06f31461082d578063ba9a7a561461084d576102f4565b806395d89b4111610145578063a9059cbb1161011f578063a9059cbb146107da578063ac9650d8146107ed578063adfca15e1461080d576102f4565b806395d89b4114610749578063981b24d014610785578063a7fe277714610798576102f4565b80637ecebe00116101765780637ecebe00146106ee57806389afcb441461070e578063903cd3e314610736576102f4565b80637464fc3d146106d05780637a0ed627146106d9576102f4565b8063313ce5671161024a5780634ee2cd7e116101fe5780635a3d5493116101d85780635a3d5493146106945780636a6278421461069d57806370a08231146106b0576102f4565b80634ee2cd7e1461066357806352ef6b2c146106765780635909c0d51461068b576102f4565b80633e13e2e31161022f5780633e13e2e314610634578063481c6a751461063d5780634c40349614610650576102f4565b8063313ce567146106125780633644e5151461062c576102f4565b80630dfe1681116102ac5780631b7d8f5e116102865780631b7d8f5e1461058c57806323b872dd146105d857806330adf81f146105eb576102f4565b80630dfe16811461054257806313966db51461056d57806318160ddd14610575576102f4565b806306fdde03116102dd57806306fdde03146104805780630902f1ac146104c9578063095ea7b31461052f576102f4565b806301ffc9a7146103f2578063022c0d9f1461046b575b600080357fffffffff000000000000000000000000000000000000000000000000000000001681527fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f27602052604081205436906060906001600160a01b0316806103a55760405162461bcd60e51b815260206004820152601b60248201527f426c617a65537761703a20494e56414c49445f46554e4354494f4e000000000060448201526064015b60405180910390fd5b6103e58185858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506109a692505050565b8051945060200192505050f35b610456610400366004613f17565b7fffffffff000000000000000000000000000000000000000000000000000000001660009081527fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f26602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61047e610479366004613f49565b610a97565b005b6104bc6040518060400160405280600981526020017f426c617a6553776170000000000000000000000000000000000000000000000081525081565b604051610462919061402f565b600854604080516dffffffffffffffffffffffffffff80841682526e01000000000000000000000000000084041660208201527c010000000000000000000000000000000000000000000000000000000090920463ffffffff1690820152606001610462565b61045661053d366004614042565b610b38565b600654610555906001600160a01b031681565b6040516001600160a01b039091168152602001610462565b61047e610b4e565b61057e60005481565b604051908152602001610462565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f25547501000000000000000000000000000000000000000000900460ff165b60405161046291906140d4565b6104566105e63660046140e7565b610be9565b61057e7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b61061a601281565b60405160ff9091168152602001610462565b61057e610c9c565b61057e600c5481565b600554610555906001600160a01b031681565b61047e61065e366004613f49565b610deb565b61057e610671366004614042565b610e83565b61067e610ed2565b6040516104629190614128565b61057e60095481565b61057e600a5481565b61057e6106ab366004614175565b610f56565b61057e6106be366004614175565b60016020526000908152604090205481565b61057e600b5481565b6106e1611351565b60405161046291906141ef565b61057e6106fc366004614175565b60036020526000908152604090205481565b61072161071c366004614175565b6114fd565b60408051928352602083019190915201610462565b61047e610744366004614299565b611952565b6104bc6040518060400160405280600881526020017f424c415a452d4c5000000000000000000000000000000000000000000000000081525081565b61057e610793366004614304565b611a9c565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f255474010000000000000000000000000000000000000000900460ff166105cb565b6104566107e8366004614042565b611ac7565b6108006107fb36600461431d565b611ad4565b6040516104629190614392565b61082061081b366004614175565b611bc9565b6040516104629190614412565b61057e61083b366004614175565b600d6020526000908152604090205481565b61057e6103e881565b61047e610864366004614175565b611cdc565b61047e610877366004614425565b611ea0565b7f52720094aed01ff34e348759e70383310167af8639ed3cc691bb00386db89cda546001600160a01b0316610555565b6105556108ba366004613f17565b7fffffffff000000000000000000000000000000000000000000000000000000001660009081527fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f2760205260409020546001600160a01b031690565b600754610555906001600160a01b031681565b61047e610937366004614470565b611f71565b61047e61094a366004614175565b6121b0565b61057e61095d3660046144e7565b600260209081526000928352604080842090915290825290205481565b61047e61260d565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f2490565b6060600080846001600160a01b0316846040516109c39190614520565b600060405180830381855af49150503d80600081146109fe576040519150601f19603f3d011682016040523d82523d6000602084013e610a03565b606091505b509150915081610a8d578051600003610a845760405162461bcd60e51b815260206004820152602960248201527f44656c656761746543616c6c48656c7065723a2072657665727420776974682060448201527f6e6f20726561736f6e0000000000000000000000000000000000000000000000606482015260840161039c565b80518082602001fd5b9150505b92915050565b600080610af36008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b5091509150610b23826008600e9054906101000a90046dffffffffffffffffffffffffffff16898989898961279e565b610b2f82826000612d63565b50505050505050565b6000610b45338484612fcb565b50600192915050565b600080610baa6008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50915091506000610bbb838361302d565b90508015610be457610be06dffffffffffffffffffffffffffff80841690851661456b565b600b555b505050565b6001600160a01b03831660009081526002602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14610c87576001600160a01b0384166000908152600260209081526040808320338452909152902054610c62908390614582565b6001600160a01b03851660009081526002602090815260408083203384529091529020555b610c9284848461337e565b5060019392505050565b6000467f000000000000000000000000000000000000000000000000000000000000000014610dc65750604080518082018252600981527f426c617a6553776170000000000000000000000000000000000000000000000060209182015281518083018352600181527f31000000000000000000000000000000000000000000000000000000000000009082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527f4f3c2418297976d44521b7127fe41c4e9949d309a364d0680ee7c3855be9a8b6818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c0909101909252815191012090565b507f000000000000000000000000000000000000000000000000000000000000000090565b600080610e476008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b5091509150610e77826008600e9054906101000a90046dffffffffffffffffffffffffffff16898989898961279e565b610b2f82826001612d63565b6001600160a01b0382166000908152600f6020526040812081908190610eaa908590613480565b9150915081610a8d57505050506001600160a01b031660009081526001602052604090205490565b60607fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f24600401805480602002602001604051908101604052809291908181526020018280548015610f4c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f2e575b5050505050905090565b6000610f60613587565b600080610fbc6008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506006546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529294509092506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104b9190614595565b6007546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156110b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d69190614595565b905060006110f46dffffffffffffffffffffffffffff861684614582565b905060006111126dffffffffffffffffffffffffffff861684614582565b90506000611120878761302d565b600080549192508190036111cb576004546103e8906001600160a01b031663677342ce61114d868861456b565b6040518263ffffffff1660e01b815260040161116b91815260200190565b602060405180830381865afa158015611188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ac9190614595565b6111b69190614582565b98506111c661dead6103e86135ff565b611220565b61121d6dffffffffffffffffffffffffffff89166111e9838761456b565b6111f391906145dd565b6dffffffffffffffffffffffffffff891661120e848761456b565b61121891906145dd565b613694565b98505b600089116112965760405162461bcd60e51b815260206004820152602860248201527f426c617a65537761703a20494e53554646494349454e545f4c4951554944495460448201527f595f4d494e544544000000000000000000000000000000000000000000000000606482015260840161039c565b6112a08a8a6135ff565b6112ac86868a8a6136ac565b81156112e0576008546dffffffffffffffffffffffffffff8082166e0100000000000000000000000000009092041602600b555b604080518581526020810185905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a2505050505050505061134c60017f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399055565b919050565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f28546060907fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f24908067ffffffffffffffff8111156113b1576113b1614618565b6040519080825280602002602001820160405280156113f757816020015b6040805180820190915260008152606060208201528152602001906001900390816113cf5790505b50925060005b818110156114f757600083600401828154811061141c5761141c614647565b9060005260206000200160009054906101000a90046001600160a01b031690506000816001600160a01b031663118a53896040518163ffffffff1660e01b8152600401600060405180830381865afa15801561147c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114a49190810190614681565b5090506040518060400160405280836001600160a01b03168152602001828152508684815181106114d7576114d7614647565b6020026020010181905250505080806114ef90614758565b9150506113fd565b50505090565b600080611508613587565b6000806115646008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506006546007546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529395509193506001600160a01b039081169291169060009083906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb9190614595565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561165e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116829190614595565b3060009081526001602052604081205491925061169f888861302d565b600054909150806116b0868561456b565b6116ba91906145dd565b9a50806116c7858561456b565b6116d191906145dd565b995060008b1180156116e3575060008a115b6117555760405162461bcd60e51b815260206004820152602860248201527f426c617a65537761703a20494e53554646494349454e545f4c4951554944495460448201527f595f4255524e4544000000000000000000000000000000000000000000000000606482015260840161039c565b61175f3084613961565b6117736001600160a01b0388168d8d6139f0565b6117876001600160a01b0387168d8c6139f0565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa1580156117e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118089190614595565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529095506001600160a01b038716906370a0823190602401602060405180830381865afa158015611868573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188c9190614595565b935061189a85858b8b6136ac565b81156118d5576008546118d1906dffffffffffffffffffffffffffff6e01000000000000000000000000000082048116911661456b565b600b555b604080518c8152602081018c90526001600160a01b038e169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050505061194d60017f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399055565b915091565b61195a613b39565b611965858585611ea0565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f2480546001600160a01b038681167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161783557fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f25805491871692821683178155859290917fffffffffffffffffffffff000000000000000000000000000000000000000000161774010000000000000000000000000000000000000000836002811115611a3657611a3661406e565b02179055506001810180548391907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000836002811115611a8f57611a8f61406e565b0217905550505050505050565b6000806000611aac846010613480565b9150915081611abd57600054611abf565b805b949350505050565b6000610b4533848461337e565b60608167ffffffffffffffff811115611aef57611aef614618565b604051908082528060200260200182016040528015611b2257816020015b6060815260200190600190039081611b0d5790505b50905060005b82811015611bc257611b9230858584818110611b4657611b46614647565b9050602002810190611b589190614790565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506109a692505050565b828281518110611ba457611ba4614647565b60200260200101819052508080611bba90614758565b915050611b28565b5092915050565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f28546060907fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f249060005b81811015611cd457846001600160a01b0316836004018281548110611c3a57611c3a614647565b6000918252602090912001546001600160a01b031603611cc257846001600160a01b031663118a53896040518163ffffffff1660e01b8152600401600060405180830381865afa158015611c92573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611cba9190810190614681565b509350611cd4565b80611ccc81614758565b915050611c13565b505050919050565b611ce4613587565b6006546007546008546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b039384169390921691611da99185916dffffffffffffffffffffffffffff9091169085906370a0823190602401602060405180830381865afa158015611d6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8e9190614595565b611d989190614582565b6001600160a01b03851691906139f0565b6008546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152611e729185916e0100000000000000000000000000009091046dffffffffffffffffffffffffffff16906001600160a01b038516906370a0823190602401602060405180830381865afa158015611e33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e579190614595565b611e619190614582565b6001600160a01b03841691906139f0565b5050611e9d60017f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399055565b50565b611ea8613b39565b826001600160a01b0316633693799b6040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ee8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f0c91906147f5565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03938416179091556005805482169583169590951790945560068054851693821693909317909255600780549093169116179055565b42841015611fc15760405162461bcd60e51b815260206004820152601260248201527f426c617a65537761703a20455850495245440000000000000000000000000000604482015260640161039c565b6000611fcb610c9c565b6001600160a01b038916600090815260036020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928c928c928c9290919061201983614758565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e001604051602081830303815290604052805190602001206040516020016120ad9291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015612118573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061214e5750886001600160a01b0316816001600160a01b0316145b61219a5760405162461bcd60e51b815260206004820152601c60248201527f426c617a65537761703a20494e56414c49445f5349474e415455524500000000604482015260640161039c565b6121a5898989612fcb565b505050505050505050565b6121b8613b39565b6000816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221c91906147f5565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f28805460018101825560009182527f4da715450b54d36aeab7c19e2e8d5921d73a0a9efc0e2769c9256f349fa5910f0180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038416908117909155604080517f118a538900000000000000000000000000000000000000000000000000000000815290519394507fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f249383929163118a538991600480830192869291908290030181865afa15801561231a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526123429190810190614681565b9150915060005b82518110156124625760006001600160a01b031684600301600085848151811061237557612375614647565b6020908102919091018101517fffffffff00000000000000000000000000000000000000000000000000000000168252810191909152604001600020546001600160a01b0316146123c557600080fd5b848460030160008584815181106123de576123de614647565b6020908102919091018101517fffffffff0000000000000000000000000000000000000000000000000000000016825281019190915260400160002080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03929092169190911790558061245a81614758565b915050612349565b50604080516001808252818301909252600091816020015b6040805160608082018352600080835260208301529181019190915281526020019060019003908161247a5790505060408051606081019091526001600160a01b0387168152909150602081016000815260200184815250816000815181106124e5576124e5614647565b602090810291909101810191909152604080516001600160a01b038916602480830191909152825180830390910181526044909101825291820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de800000000000000000000000000000000000000000000000000000000179052517f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6739061259590849089908590614812565b60405180910390a17fffffffff0000000000000000000000000000000000000000000000000000000083166000908152600286016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561260386826109a6565b5050505050505050565b612615613587565b6006546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015261274f916001600160a01b0316906370a0823190602401602060405180830381865afa158015612678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269c9190614595565b6007546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156126fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127219190614595565b6008546dffffffffffffffffffffffffffff808216916e0100000000000000000000000000009004166136ac565b61277860017f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399055565b565b7f52720094aed01ff34e348759e70383310167af8639ed3cc691bb00386db89cda90565b6127a6613587565b60008511806127b55750600084115b6128275760405162461bcd60e51b815260206004820152602560248201527f426c617a65537761703a20494e53554646494349454e545f4f55545055545f4160448201527f4d4f554e54000000000000000000000000000000000000000000000000000000606482015260840161039c565b866dffffffffffffffffffffffffffff16851080156128555750856dffffffffffffffffffffffffffff1684105b6128c75760405162461bcd60e51b815260206004820152602160248201527f426c617a65537761703a20494e53554646494349454e545f4c4951554944495460448201527f5900000000000000000000000000000000000000000000000000000000000000606482015260840161039c565b60065460075460009182916001600160a01b039182169190811690871682148015906129055750806001600160a01b0316876001600160a01b031614155b6129515760405162461bcd60e51b815260206004820152601560248201527f426c617a65537761703a20494e56414c49445f544f0000000000000000000000604482015260640161039c565b881561296b5761296b6001600160a01b038316888b6139f0565b8715612985576129856001600160a01b038216888a6139f0565b8415612a0b576040517ffe8818420000000000000000000000000000000000000000000000000000000081526001600160a01b0388169063fe881842906129d89033908d908d908c908c906004016148e4565b600060405180830381600087803b1580156129f257600080fd5b505af1158015612a06573d6000803e3d6000fd5b505050505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c9190614595565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015612aec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b109190614595565b92505050600080888b6dffffffffffffffffffffffffffff16038411612b37576000612b4d565b888b6dffffffffffffffffffffffffffff160384035b9150878a6dffffffffffffffffffffffffffff16038311612b6f576000612b85565b878a6dffffffffffffffffffffffffffff160383035b90506000821180612b965750600081115b612c075760405162461bcd60e51b8152602060048201526024808201527f426c617a65537761703a20494e53554646494349454e545f494e5055545f414d60448201527f4f554e5400000000000000000000000000000000000000000000000000000000606482015260840161039c565b6000612c1483600361456b565b612c20866103e861456b565b612c2a9190614582565b90506000612c3983600361456b565b612c45866103e861456b565b612c4f9190614582565b9050612c6e6dffffffffffffffffffffffffffff808e16908f1661456b565b612c7b90620f424061456b565b612c85828461456b565b1015612cd35760405162461bcd60e51b815260206004820152600c60248201527f426c617a65537761703a204b0000000000000000000000000000000000000000604482015260640161039c565b5050612ce184848d8d6136ac565b60408051838152602081018390529081018a9052606081018990526001600160a01b0388169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350505050610b2f60017f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399055565b600b5415610be457600080612dc76008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50915091506000846dffffffffffffffffffffffffffff16866dffffffffffffffffffffffffffff16612dfa919061456b565b612e176dffffffffffffffffffffffffffff80851690861661456b565b612e219190614582565b905080600c6000828254612e359190614931565b90915550508315612fc3576005546040517f88720d8c00000000000000000000000000000000000000000000000000000000815233600482015260009182916001600160a01b03909116906388720d8c906024016040805180830381865afa158015612ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ec99190614944565b90925090506001600160a01b03821615801590612ee65750600081115b15612603576000612710612efa838661456b565b612f0491906145dd565b905083156121a5576001600160a01b0383166000908152600d602052604081205490819003612f9157600e80546001810182556000919091527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd0180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386161790555b6001600160a01b0384166000908152600d602052604081208054849290612fb9908490614931565b9091555050505050505b505050505050565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600080600560009054906101000a90046001600160a01b03166001600160a01b0316635ab7b6166040518163ffffffff1660e01b8152600401602060405180830381865afa158015613083573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a791906147f5565b600b546001600160a01b03821615801594509192509061336357801561335e576004546000906001600160a01b031663677342ce6130f86dffffffffffffffffffffffffffff808916908a1661456b565b6040518263ffffffff1660e01b815260040161311691815260200190565b602060405180830381865afa158015613133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131579190614595565b600480546040517f677342ce0000000000000000000000000000000000000000000000000000000081529182018590529192506000916001600160a01b03169063677342ce90602401602060405180830381865afa1580156131bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e19190614595565b9050808211156133535760006131f78284614582565b600054613204919061456b565b905060008261321485600561456b565b61321e9190614931565b9050600061322c82846145dd565b9050801561334f5760005b600e5481101561333e576000600e828154811061325657613256614647565b600091825260208083209190910154600480546001600160a01b03928316808652600d909452604080862054600c5491517faa9a09120000000000000000000000000000000000000000000000000000000081529384018a90526024840152604483015292945091169063aa9a091290606401602060405180830381865afa1580156132e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330a9190614595565b905080156133295761331c82826135ff565b6133268185614582565b93505b5050808061333690614758565b915050613237565b50801561334f5761334f87826135ff565b5050505b61335b613bb2565b50505b613376565b8015613376576000600b55613376613bb2565b505092915050565b6001600160a01b0382166133d45760405162461bcd60e51b815260206004820152601760248201527f426c617a65537761703a205a45524f5f41444452455353000000000000000000604482015260640161039c565b6133df838383613c8a565b6001600160a01b03831660009081526001602052604081208054839290613407908490614582565b90915550506001600160a01b03821660009081526001602052604081208054839290613434908490614931565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161302091815260200190565b600080438411156134d35760405162461bcd60e51b815260206004820152601e60248201527f426c617a65537761703a20494e56414c49445f534e415053484f545f49440000604482015260640161039c565b82546000905b8082101561354257600060026134ef8385614931565b6134f991906145dd565b90508686828154811061350e5761350e614647565b906000526020600020906002020160000154111561352e5780915061353c565b613539816001614931565b92505b506134d9565b8454821061355257600080613579565b600185838154811061356657613566614647565b9060005260206000209060020201600101545b9350935050505b9250929050565b7f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399080546002036135f95760405162461bcd60e51b815260206004820152601e60248201527f5265656e7472616e63794c6f636b3a207265656e7472616e742063616c6c0000604482015260640161039c565b60029055565b61360b60008383613c8a565b8060008082825461361c9190614931565b90915550506001600160a01b03821660009081526001602052604081208054839290613649908490614931565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b60008183106136a357816136a5565b825b9392505050565b6dffffffffffffffffffffffffffff84118015906136d857506dffffffffffffffffffffffffffff8311155b6137245760405162461bcd60e51b815260206004820152601360248201527f426c617a65537761703a204f564552464c4f5700000000000000000000000000604482015260640161039c565b60085463ffffffff428116917c01000000000000000000000000000000000000000000000000000000009004811682039081161580159061377457506dffffffffffffffffffffffffffff841615155b801561378f57506dffffffffffffffffffffffffffff831615155b156138715763ffffffff81166137e6856e0100000000000000000000000000006dffffffffffffffffffffffffffff8716025b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690613d94565b600980547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092169290920201905563ffffffff8116613844846e0100000000000000000000000000006dffffffffffffffffffffffffffff8816026137c2565b600a80547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216929092020190555b506008805463ffffffff83167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff8881166e0100000000000000000000000000009081027fffffffff000000000000000000000000000000000000000000000000000000009095168b83161794909417918216831794859055604080519382169282169290921783529290930490911660208201527f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a15050505050565b61396d82600083613c8a565b6001600160a01b03821660009081526001602052604081208054839290613995908490614582565b92505081905550806000808282546139ad9190614582565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001613688565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691613a7a9190614520565b6000604051808303816000865af19150503d8060008114613ab7576040519150601f19603f3d011682016040523d82523d6000602084013e613abc565b606091505b5091509150818015613ae6575080511580613ae6575080806020019051810190613ae69190614972565b613b325760405162461bcd60e51b815260206004820152601c60248201527f5472616e7366657248656c7065723a3a736166655472616e7366657200000000604482015260640161039c565b5050505050565b337f52720094aed01ff34e348759e70383310167af8639ed3cc691bb00386db89cda546001600160a01b0316146127785760405162461bcd60e51b815260206004820152601960248201527f506172656e7452656c6174696f6e3a20464f5242494444454e00000000000000604482015260640161039c565b600e545b8015613c82576000600e613bcb600184614582565b81548110613bdb57613bdb614647565b60009182526020808320909101546001600160a01b0316808352600d9091526040822091909155600e80549192509080613c1757613c17614994565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190555080613c7a816149c3565b915050613bb6565b506000600c55565b613c95838383613ddb565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f28547fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f249015613d8e57600081600401600081548110613cf657613cf6614647565b60009182526020918290200154604080516001600160a01b0389811660248301528881166044830152606480830189905283518084039091018152608490920190925292830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2f8358b600000000000000000000000000000000000000000000000000000000179052169150612fc39082906109a6565b50505050565b60006dffffffffffffffffffffffffffff82167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841681613dd357613dd36145ae565b049392505050565b610be483836001600160a01b038216613e0357613df781613e28565b613dff613e56565b5050565b6001600160a01b038116613e1a57613df782613e28565b613e2382613e28565b613dff815b6001600160a01b0381166000908152600f60209081526040808320600190925290912054611e9d9190613e5f565b61277860106000545b815460009015613ea05782548390613e7990600190614582565b81548110613e8957613e89614647565b906000526020600020906002020160000154613ea3565b60005b905043811015610be45750604080518082019091524381526020808201928352835460018082018655600095865291909420915160029094029091019283559051910155565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611e9d57600080fd5b600060208284031215613f2957600080fd5b81356136a581613ee9565b6001600160a01b0381168114611e9d57600080fd5b600080600080600060808688031215613f6157600080fd5b85359450602086013593506040860135613f7a81613f34565b9250606086013567ffffffffffffffff80821115613f9757600080fd5b818801915088601f830112613fab57600080fd5b813581811115613fba57600080fd5b896020828501011115613fcc57600080fd5b9699959850939650602001949392505050565b60005b83811015613ffa578181015183820152602001613fe2565b50506000910152565b6000815180845261401b816020860160208601613fdf565b601f01601f19169290920160200192915050565b6020815260006136a56020830184614003565b6000806040838503121561405557600080fd5b823561406081613f34565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110611e9d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016140e18361409d565b91905290565b6000806000606084860312156140fc57600080fd5b833561410781613f34565b9250602084013561411781613f34565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b818110156141695783516001600160a01b031683529284019291840191600101614144565b50909695505050505050565b60006020828403121561418757600080fd5b81356136a581613f34565b600081518084526020808501945080840160005b838110156141e45781517fffffffff0000000000000000000000000000000000000000000000000000000016875295820195908201906001016141a6565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561427c578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018552815180516001600160a01b0316845287015187840187905261426987850182614192565b9588019593505090860190600101614216565b509098975050505050505050565b80356003811061134c57600080fd5b600080600080600060a086880312156142b157600080fd5b85356142bc81613f34565b945060208601356142cc81613f34565b935060408601356142dc81613f34565b92506142ea6060870161428a565b91506142f86080870161428a565b90509295509295909350565b60006020828403121561431657600080fd5b5035919050565b6000806020838503121561433057600080fd5b823567ffffffffffffffff8082111561434857600080fd5b818501915085601f83011261435c57600080fd5b81358181111561436b57600080fd5b8660208260051b850101111561438057600080fd5b60209290920196919550909350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015614405577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526143f3858351614003565b945092850192908501906001016143b9565b5092979650505050505050565b6020815260006136a56020830184614192565b60008060006060848603121561443a57600080fd5b833561444581613f34565b9250602084013561445581613f34565b9150604084013561446581613f34565b809150509250925092565b600080600080600080600060e0888a03121561448b57600080fd5b873561449681613f34565b965060208801356144a681613f34565b95506040880135945060608801359350608088013560ff811681146144ca57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156144fa57600080fd5b823561450581613f34565b9150602083013561451581613f34565b809150509250929050565b60008251614532818460208701613fdf565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610a9157610a9161453c565b81810381811115610a9157610a9161453c565b6000602082840312156145a757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614613577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805161134c81613ee9565b6000806040838503121561469457600080fd5b825167ffffffffffffffff808211156146ac57600080fd5b818501915085601f8301126146c057600080fd5b81516020828211156146d4576146d4614618565b8160051b604051601f19603f830116810181811086821117156146f9576146f9614618565b60405292835281830193508481018201928984111561471757600080fd5b948201945b8386101561473c5761472d86614676565b8552948201949382019361471c565b965061474b9050878201614676565b9450505050509250929050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036147895761478961453c565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126147c557600080fd5b83018035915067ffffffffffffffff8211156147e057600080fd5b60200191503681900382131561358057600080fd5b60006020828403121561480757600080fd5b81516136a581613f34565b6000606080830181845280875180835260808601915060808160051b87010192506020808a0160005b838110156148b5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8089870301855281516001600160a01b038151168752838101516148868161409d565b878501526040908101519087018890526148a288880182614192565b965050938201939082019060010161483b565b50506001600160a01b03891690870152505083810360408501526148d98186614003565b979650505050505050565b6001600160a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b80820180821115610a9157610a9161453c565b6000806040838503121561495757600080fd5b825161496281613f34565b6020939093015192949293505050565b60006020828403121561498457600080fd5b815180151581146136a557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000816149d2576149d261453c565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c6343000811000aa164736f6c6343000811000a000000000000000000000000e007fd6bcbf3474a186b66bbe8ad1c373b86bc6b

Deployed ByteCode

0x60806040523480156200001157600080fd5b5060043610620000875760003560e01c806364b3b82a116200006257806364b3b82a1462000107578063926d8c331462000120578063c9c653961462000157578063e6a43905146200016e57600080fd5b80631e3dd18b146200008c578063481c6a7514620000cd578063574f2ba314620000f5575b600080fd5b620000a36200009d366004620010ea565b620001af565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b620000a37f000000000000000000000000e007fd6bcbf3474a186b66bbe8ad1c373b86bc6b81565b600154604051908152602001620000c4565b6200011e620001183660046200112a565b620001e7565b005b62000146620001313660046200112a565b60026020526000908152604090205460ff1681565b6040519015158152602001620000c4565b620000a36200016836600462001151565b620003f7565b620000a36200017f36600462001151565b600060208181529281526040808220909352908152205473ffffffffffffffffffffffffffffffffffffffff1681565b60018181548110620001c057600080fd5b60009182526020909120015473ffffffffffffffffffffffffffffffffffffffff16905081565b60007f000000000000000000000000e007fd6bcbf3474a186b66bbe8ad1c373b86bc6b905060008173ffffffffffffffffffffffffffffffffffffffff166309b58a656040518163ffffffff1660e01b8152600401602060405180830381865afa1580156200025a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200028091906200118f565b905073ffffffffffffffffffffffffffffffffffffffff811615801590620002cd575073ffffffffffffffffffffffffffffffffffffffff831660009081526002602052604090205460ff165b62000339576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f426c617a65537761703a20555047524144455f4e4f545f4e454544454400000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8381166000818152600260205260409081902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517fd8867fc800000000000000000000000000000000000000000000000000000000815291831660048301529063d8867fc8906024015b600060405180830381600087803b158015620003d957600080fd5b505af1158015620003ee573d6000803e3d6000fd5b50505050505050565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff160362000490576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601e60248201527f426c617a65537761703a204944454e544943414c5f4144445245535345530000604482015260640162000330565b6000808373ffffffffffffffffffffffffffffffffffffffff168573ffffffffffffffffffffffffffffffffffffffff1610620004cf578385620004d2565b84845b909250905073ffffffffffffffffffffffffffffffffffffffff821662000556576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f426c617a65537761703a205a45524f5f41444452455353000000000000000000604482015260640162000330565b73ffffffffffffffffffffffffffffffffffffffff82811660009081526020818152604080832085851684529091529020541615620005f2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f426c617a65537761703a20504149525f45584953545300000000000000000000604482015260640162000330565b6040517fffffffffffffffffffffffffffffffffffffffff000000000000000000000000606084811b8216602084015283901b16603482015260009060480160405160208183030381529060405280519060200120905060006200065562000767565b9050818151602083016000f5945062000670858585620007b1565b73ffffffffffffffffffffffffffffffffffffffff84811660008181526020818152604080832088861680855290835281842080547fffffffffffffffffffffffff0000000000000000000000000000000000000000908116978d1697881790915584845282852086865284528285208054821688179055600180548082018255958190527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6909501805490911687179055925481519586529185019190915290927f0d3648bd0f6ba80134a33ba9275ac585d9d315f0ad8355cddefde31afa28d0e9910160405180910390a35050505092915050565b6060604051806020016200077b90620010dc565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820381018352601f90910116604052919050565b620007be83838362001057565b6040517f93272baf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301527f000000000000000000000000e007fd6bcbf3474a186b66bbe8ad1c373b86bc6b918591600091908416906393272baf90602401602060405180830381865afa15801562000853573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620008799190620011bd565b6040517f93272baf00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff86811660048301529192506000918516906393272baf90602401602060405180830381865afa158015620008ec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620009129190620011bd565b6040517f903cd3e300000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff84169063903cd3e39062000991907f000000000000000000000000e007fd6bcbf3474a186b66bbe8ad1c373b86bc6b908a908a908890889060040162001248565b600060405180830381600087803b158015620009ac57600080fd5b505af1158015620009c1573d6000803e3d6000fd5b5060009250620009cf915050565b826002811115620009e457620009e4620011dd565b14158062000a075750600081600281111562000a045762000a04620011dd565b14155b15620003ee578273ffffffffffffffffffffffffffffffffffffffff1663d8867fc88573ffffffffffffffffffffffffffffffffffffffff1663d68492106040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000a75573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000a9b91906200118f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401600060405180830381600087803b15801562000b0257600080fd5b505af115801562000b17573d6000803e3d6000fd5b506001925062000b25915050565b82600281111562000b3a5762000b3a620011dd565b148062000b5b5750600181600281111562000b595762000b59620011dd565b145b1562000d94578273ffffffffffffffffffffffffffffffffffffffff1663d8867fc88573ffffffffffffffffffffffffffffffffffffffff1663e6030c5d6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000bc9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000bef91906200118f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401600060405180830381600087803b15801562000c5657600080fd5b505af115801562000c6b573d6000803e3d6000fd5b5050505046600e148062000c7f5750466072145b1562000d94578273ffffffffffffffffffffffffffffffffffffffff1663d8867fc88573ffffffffffffffffffffffffffffffffffffffff1663d1f133b66040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000ced573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000d1391906200118f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401600060405180830381600087803b15801562000d7a57600080fd5b505af115801562000d8f573d6000803e3d6000fd5b505050505b600282600281111562000dab5762000dab620011dd565b148062000dcc5750600281600281111562000dca5762000dca620011dd565b145b15620003ee5760008473ffffffffffffffffffffffffffffffffffffffff16630d92c1ca6040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000e20573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000e469190620011bd565b9050600281600281111562000e5f5762000e5f620011dd565b0362000f79578373ffffffffffffffffffffffffffffffffffffffff1663d8867fc88673ffffffffffffffffffffffffffffffffffffffff166309b58a656040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000ecd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ef391906200118f565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815273ffffffffffffffffffffffffffffffffffffffff9091166004820152602401600060405180830381600087803b15801562000f5a57600080fd5b505af115801562000f6f573d6000803e3d6000fd5b505050506200104d565b600181600281111562000f905762000f90620011dd565b0362000fea5773ffffffffffffffffffffffffffffffffffffffff8816600090815260026020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556200104d565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f426c617a65537761703a204641535345545f554e535550504f52544544000000604482015260640162000330565b5050505050505050565b6040517fc0c53b8b00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000e007fd6bcbf3474a186b66bbe8ad1c373b86bc6b811660048301528381166024830152828116604483015284169063c0c53b8b90606401620003be565b614c95806200129e83390190565b600060208284031215620010fd57600080fd5b5035919050565b73ffffffffffffffffffffffffffffffffffffffff811681146200112757600080fd5b50565b6000602082840312156200113d57600080fd5b81356200114a8162001104565b9392505050565b600080604083850312156200116557600080fd5b8235620011728162001104565b91506020830135620011848162001104565b809150509250929050565b600060208284031215620011a257600080fd5b81516200114a8162001104565b600381106200112757600080fd5b600060208284031215620011d057600080fd5b81516200114a81620011af565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b6003811062001244577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b9052565b73ffffffffffffffffffffffffffffffffffffffff868116825285811660208301528416604082015260a081016200128460608301856200120c565b6200129360808301846200120c565b969550505050505056fe60c06040523480156200001157600080fd5b5046608052620000ea60408051808201825260098152680426c617a65537761760bc1b6020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527f4f3c2418297976d44521b7127fe41c4e9949d309a364d0680ee7c3855be9a8b6818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c0909101909252815191012090565b60a052620000f833620001eb565b60006200010f6200022260201b620009821760201c565b6348e2b09360e01b600090815260029091016020526040808220805460ff1990811660019081179092556301ffc9a760e01b845282842080548216831790556336372b0760e01b8452828420805482168317905563a219a02560e01b84528284208054821683179055634ec7fbed60e11b84528284208054821683179055636b7cf4d760e11b84528284208054821683179055631592ca1b60e31b84528284208054821683179055636a865ca360e01b8452828420805482168317905563bc83a82960e01b84529190922080549091169091179055506200026a565b80620002016200024660201b6200277a1760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f2490565b7f52720094aed01ff34e348759e70383310167af8639ed3cc691bb00386db89cda90565b60805160a051614a05620002906000396000610dc901526000610ca10152614a056000f3fe608060405234801561001057600080fd5b50600436106102f45760003560e01c80637464fc3d11610191578063b41a06f3116100e3578063cdffacc611610097578063d8867fc811610071578063d8867fc81461093c578063dd62ed3e1461094f578063fff6cae91461097a576102f4565b8063cdffacc6146108ac578063d21220a714610916578063d505accf14610929576102f4565b8063bc25cf77116100c8578063bc25cf7714610856578063c0c53b8b14610869578063c45a01551461087c576102f4565b8063b41a06f31461082d578063ba9a7a561461084d576102f4565b806395d89b4111610145578063a9059cbb1161011f578063a9059cbb146107da578063ac9650d8146107ed578063adfca15e1461080d576102f4565b806395d89b4114610749578063981b24d014610785578063a7fe277714610798576102f4565b80637ecebe00116101765780637ecebe00146106ee57806389afcb441461070e578063903cd3e314610736576102f4565b80637464fc3d146106d05780637a0ed627146106d9576102f4565b8063313ce5671161024a5780634ee2cd7e116101fe5780635a3d5493116101d85780635a3d5493146106945780636a6278421461069d57806370a08231146106b0576102f4565b80634ee2cd7e1461066357806352ef6b2c146106765780635909c0d51461068b576102f4565b80633e13e2e31161022f5780633e13e2e314610634578063481c6a751461063d5780634c40349614610650576102f4565b8063313ce567146106125780633644e5151461062c576102f4565b80630dfe1681116102ac5780631b7d8f5e116102865780631b7d8f5e1461058c57806323b872dd146105d857806330adf81f146105eb576102f4565b80630dfe16811461054257806313966db51461056d57806318160ddd14610575576102f4565b806306fdde03116102dd57806306fdde03146104805780630902f1ac146104c9578063095ea7b31461052f576102f4565b806301ffc9a7146103f2578063022c0d9f1461046b575b600080357fffffffff000000000000000000000000000000000000000000000000000000001681527fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f27602052604081205436906060906001600160a01b0316806103a55760405162461bcd60e51b815260206004820152601b60248201527f426c617a65537761703a20494e56414c49445f46554e4354494f4e000000000060448201526064015b60405180910390fd5b6103e58185858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506109a692505050565b8051945060200192505050f35b610456610400366004613f17565b7fffffffff000000000000000000000000000000000000000000000000000000001660009081527fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f26602052604090205460ff1690565b60405190151581526020015b60405180910390f35b61047e610479366004613f49565b610a97565b005b6104bc6040518060400160405280600981526020017f426c617a6553776170000000000000000000000000000000000000000000000081525081565b604051610462919061402f565b600854604080516dffffffffffffffffffffffffffff80841682526e01000000000000000000000000000084041660208201527c010000000000000000000000000000000000000000000000000000000090920463ffffffff1690820152606001610462565b61045661053d366004614042565b610b38565b600654610555906001600160a01b031681565b6040516001600160a01b039091168152602001610462565b61047e610b4e565b61057e60005481565b604051908152602001610462565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f25547501000000000000000000000000000000000000000000900460ff165b60405161046291906140d4565b6104566105e63660046140e7565b610be9565b61057e7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b61061a601281565b60405160ff9091168152602001610462565b61057e610c9c565b61057e600c5481565b600554610555906001600160a01b031681565b61047e61065e366004613f49565b610deb565b61057e610671366004614042565b610e83565b61067e610ed2565b6040516104629190614128565b61057e60095481565b61057e600a5481565b61057e6106ab366004614175565b610f56565b61057e6106be366004614175565b60016020526000908152604090205481565b61057e600b5481565b6106e1611351565b60405161046291906141ef565b61057e6106fc366004614175565b60036020526000908152604090205481565b61072161071c366004614175565b6114fd565b60408051928352602083019190915201610462565b61047e610744366004614299565b611952565b6104bc6040518060400160405280600881526020017f424c415a452d4c5000000000000000000000000000000000000000000000000081525081565b61057e610793366004614304565b611a9c565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f255474010000000000000000000000000000000000000000900460ff166105cb565b6104566107e8366004614042565b611ac7565b6108006107fb36600461431d565b611ad4565b6040516104629190614392565b61082061081b366004614175565b611bc9565b6040516104629190614412565b61057e61083b366004614175565b600d6020526000908152604090205481565b61057e6103e881565b61047e610864366004614175565b611cdc565b61047e610877366004614425565b611ea0565b7f52720094aed01ff34e348759e70383310167af8639ed3cc691bb00386db89cda546001600160a01b0316610555565b6105556108ba366004613f17565b7fffffffff000000000000000000000000000000000000000000000000000000001660009081527fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f2760205260409020546001600160a01b031690565b600754610555906001600160a01b031681565b61047e610937366004614470565b611f71565b61047e61094a366004614175565b6121b0565b61057e61095d3660046144e7565b600260209081526000928352604080842090915290825290205481565b61047e61260d565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f2490565b6060600080846001600160a01b0316846040516109c39190614520565b600060405180830381855af49150503d80600081146109fe576040519150601f19603f3d011682016040523d82523d6000602084013e610a03565b606091505b509150915081610a8d578051600003610a845760405162461bcd60e51b815260206004820152602960248201527f44656c656761746543616c6c48656c7065723a2072657665727420776974682060448201527f6e6f20726561736f6e0000000000000000000000000000000000000000000000606482015260840161039c565b80518082602001fd5b9150505b92915050565b600080610af36008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b5091509150610b23826008600e9054906101000a90046dffffffffffffffffffffffffffff16898989898961279e565b610b2f82826000612d63565b50505050505050565b6000610b45338484612fcb565b50600192915050565b600080610baa6008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50915091506000610bbb838361302d565b90508015610be457610be06dffffffffffffffffffffffffffff80841690851661456b565b600b555b505050565b6001600160a01b03831660009081526002602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff14610c87576001600160a01b0384166000908152600260209081526040808320338452909152902054610c62908390614582565b6001600160a01b03851660009081526002602090815260408083203384529091529020555b610c9284848461337e565b5060019392505050565b6000467f000000000000000000000000000000000000000000000000000000000000000014610dc65750604080518082018252600981527f426c617a6553776170000000000000000000000000000000000000000000000060209182015281518083018352600181527f31000000000000000000000000000000000000000000000000000000000000009082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818301527f4f3c2418297976d44521b7127fe41c4e9949d309a364d0680ee7c3855be9a8b6818401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a0808301919091528351808303909101815260c0909101909252815191012090565b507f000000000000000000000000000000000000000000000000000000000000000090565b600080610e476008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b5091509150610e77826008600e9054906101000a90046dffffffffffffffffffffffffffff16898989898961279e565b610b2f82826001612d63565b6001600160a01b0382166000908152600f6020526040812081908190610eaa908590613480565b9150915081610a8d57505050506001600160a01b031660009081526001602052604090205490565b60607fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f24600401805480602002602001604051908101604052809291908181526020018280548015610f4c57602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311610f2e575b5050505050905090565b6000610f60613587565b600080610fbc6008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506006546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529294509092506000916001600160a01b03909116906370a0823190602401602060405180830381865afa158015611027573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104b9190614595565b6007546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529192506000916001600160a01b03909116906370a0823190602401602060405180830381865afa1580156110b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110d69190614595565b905060006110f46dffffffffffffffffffffffffffff861684614582565b905060006111126dffffffffffffffffffffffffffff861684614582565b90506000611120878761302d565b600080549192508190036111cb576004546103e8906001600160a01b031663677342ce61114d868861456b565b6040518263ffffffff1660e01b815260040161116b91815260200190565b602060405180830381865afa158015611188573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111ac9190614595565b6111b69190614582565b98506111c661dead6103e86135ff565b611220565b61121d6dffffffffffffffffffffffffffff89166111e9838761456b565b6111f391906145dd565b6dffffffffffffffffffffffffffff891661120e848761456b565b61121891906145dd565b613694565b98505b600089116112965760405162461bcd60e51b815260206004820152602860248201527f426c617a65537761703a20494e53554646494349454e545f4c4951554944495460448201527f595f4d494e544544000000000000000000000000000000000000000000000000606482015260840161039c565b6112a08a8a6135ff565b6112ac86868a8a6136ac565b81156112e0576008546dffffffffffffffffffffffffffff8082166e0100000000000000000000000000009092041602600b555b604080518581526020810185905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a2505050505050505061134c60017f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399055565b919050565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f28546060907fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f24908067ffffffffffffffff8111156113b1576113b1614618565b6040519080825280602002602001820160405280156113f757816020015b6040805180820190915260008152606060208201528152602001906001900390816113cf5790505b50925060005b818110156114f757600083600401828154811061141c5761141c614647565b9060005260206000200160009054906101000a90046001600160a01b031690506000816001600160a01b031663118a53896040518163ffffffff1660e01b8152600401600060405180830381865afa15801561147c573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526114a49190810190614681565b5090506040518060400160405280836001600160a01b03168152602001828152508684815181106114d7576114d7614647565b6020026020010181905250505080806114ef90614758565b9150506113fd565b50505090565b600080611508613587565b6000806115646008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506006546007546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529395509193506001600160a01b039081169291169060009083906370a0823190602401602060405180830381865afa1580156115d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115fb9190614595565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529091506000906001600160a01b038416906370a0823190602401602060405180830381865afa15801561165e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116829190614595565b3060009081526001602052604081205491925061169f888861302d565b600054909150806116b0868561456b565b6116ba91906145dd565b9a50806116c7858561456b565b6116d191906145dd565b995060008b1180156116e3575060008a115b6117555760405162461bcd60e51b815260206004820152602860248201527f426c617a65537761703a20494e53554646494349454e545f4c4951554944495460448201527f595f4255524e4544000000000000000000000000000000000000000000000000606482015260840161039c565b61175f3084613961565b6117736001600160a01b0388168d8d6139f0565b6117876001600160a01b0387168d8c6139f0565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038816906370a0823190602401602060405180830381865afa1580156117e4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118089190614595565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529095506001600160a01b038716906370a0823190602401602060405180830381865afa158015611868573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061188c9190614595565b935061189a85858b8b6136ac565b81156118d5576008546118d1906dffffffffffffffffffffffffffff6e01000000000000000000000000000082048116911661456b565b600b555b604080518c8152602081018c90526001600160a01b038e169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a350505050505050505061194d60017f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399055565b915091565b61195a613b39565b611965858585611ea0565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f2480546001600160a01b038681167fffffffffffffffffffffffff00000000000000000000000000000000000000009283161783557fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f25805491871692821683178155859290917fffffffffffffffffffffff000000000000000000000000000000000000000000161774010000000000000000000000000000000000000000836002811115611a3657611a3661406e565b02179055506001810180548391907fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000836002811115611a8f57611a8f61406e565b0217905550505050505050565b6000806000611aac846010613480565b9150915081611abd57600054611abf565b805b949350505050565b6000610b4533848461337e565b60608167ffffffffffffffff811115611aef57611aef614618565b604051908082528060200260200182016040528015611b2257816020015b6060815260200190600190039081611b0d5790505b50905060005b82811015611bc257611b9230858584818110611b4657611b46614647565b9050602002810190611b589190614790565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506109a692505050565b828281518110611ba457611ba4614647565b60200260200101819052508080611bba90614758565b915050611b28565b5092915050565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f28546060907fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f249060005b81811015611cd457846001600160a01b0316836004018281548110611c3a57611c3a614647565b6000918252602090912001546001600160a01b031603611cc257846001600160a01b031663118a53896040518163ffffffff1660e01b8152600401600060405180830381865afa158015611c92573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611cba9190810190614681565b509350611cd4565b80611ccc81614758565b915050611c13565b505050919050565b611ce4613587565b6006546007546008546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b039384169390921691611da99185916dffffffffffffffffffffffffffff9091169085906370a0823190602401602060405180830381865afa158015611d6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d8e9190614595565b611d989190614582565b6001600160a01b03851691906139f0565b6008546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152611e729185916e0100000000000000000000000000009091046dffffffffffffffffffffffffffff16906001600160a01b038516906370a0823190602401602060405180830381865afa158015611e33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e579190614595565b611e619190614582565b6001600160a01b03841691906139f0565b5050611e9d60017f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399055565b50565b611ea8613b39565b826001600160a01b0316633693799b6040518163ffffffff1660e01b81526004016020604051808303816000875af1158015611ee8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f0c91906147f5565b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000009081166001600160a01b03938416179091556005805482169583169590951790945560068054851693821693909317909255600780549093169116179055565b42841015611fc15760405162461bcd60e51b815260206004820152601260248201527f426c617a65537761703a20455850495245440000000000000000000000000000604482015260640161039c565b6000611fcb610c9c565b6001600160a01b038916600090815260036020526040812080547f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928c928c928c9290919061201983614758565b909155506040805160208101969096526001600160a01b0394851690860152929091166060840152608083015260a082015260c0810187905260e001604051602081830303815290604052805190602001206040516020016120ad9291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b60408051601f198184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015612118573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381161580159061214e5750886001600160a01b0316816001600160a01b0316145b61219a5760405162461bcd60e51b815260206004820152601c60248201527f426c617a65537761703a20494e56414c49445f5349474e415455524500000000604482015260640161039c565b6121a5898989612fcb565b505050505050505050565b6121b8613b39565b6000816001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156121f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221c91906147f5565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f28805460018101825560009182527f4da715450b54d36aeab7c19e2e8d5921d73a0a9efc0e2769c9256f349fa5910f0180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b038416908117909155604080517f118a538900000000000000000000000000000000000000000000000000000000815290519394507fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f249383929163118a538991600480830192869291908290030181865afa15801561231a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526123429190810190614681565b9150915060005b82518110156124625760006001600160a01b031684600301600085848151811061237557612375614647565b6020908102919091018101517fffffffff00000000000000000000000000000000000000000000000000000000168252810191909152604001600020546001600160a01b0316146123c557600080fd5b848460030160008584815181106123de576123de614647565b6020908102919091018101517fffffffff0000000000000000000000000000000000000000000000000000000016825281019190915260400160002080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03929092169190911790558061245a81614758565b915050612349565b50604080516001808252818301909252600091816020015b6040805160608082018352600080835260208301529181019190915281526020019060019003908161247a5790505060408051606081019091526001600160a01b0387168152909150602081016000815260200184815250816000815181106124e5576124e5614647565b602090810291909101810191909152604080516001600160a01b038916602480830191909152825180830390910181526044909101825291820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fc4d66de800000000000000000000000000000000000000000000000000000000179052517f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6739061259590849089908590614812565b60405180910390a17fffffffff0000000000000000000000000000000000000000000000000000000083166000908152600286016020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905561260386826109a6565b5050505050505050565b612615613587565b6006546040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015261274f916001600160a01b0316906370a0823190602401602060405180830381865afa158015612678573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061269c9190614595565b6007546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156126fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127219190614595565b6008546dffffffffffffffffffffffffffff808216916e0100000000000000000000000000009004166136ac565b61277860017f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399055565b565b7f52720094aed01ff34e348759e70383310167af8639ed3cc691bb00386db89cda90565b6127a6613587565b60008511806127b55750600084115b6128275760405162461bcd60e51b815260206004820152602560248201527f426c617a65537761703a20494e53554646494349454e545f4f55545055545f4160448201527f4d4f554e54000000000000000000000000000000000000000000000000000000606482015260840161039c565b866dffffffffffffffffffffffffffff16851080156128555750856dffffffffffffffffffffffffffff1684105b6128c75760405162461bcd60e51b815260206004820152602160248201527f426c617a65537761703a20494e53554646494349454e545f4c4951554944495460448201527f5900000000000000000000000000000000000000000000000000000000000000606482015260840161039c565b60065460075460009182916001600160a01b039182169190811690871682148015906129055750806001600160a01b0316876001600160a01b031614155b6129515760405162461bcd60e51b815260206004820152601560248201527f426c617a65537761703a20494e56414c49445f544f0000000000000000000000604482015260640161039c565b881561296b5761296b6001600160a01b038316888b6139f0565b8715612985576129856001600160a01b038216888a6139f0565b8415612a0b576040517ffe8818420000000000000000000000000000000000000000000000000000000081526001600160a01b0388169063fe881842906129d89033908d908d908c908c906004016148e4565b600060405180830381600087803b1580156129f257600080fd5b505af1158015612a06573d6000803e3d6000fd5b505050505b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015612a68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a8c9190614595565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529094506001600160a01b038216906370a0823190602401602060405180830381865afa158015612aec573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b109190614595565b92505050600080888b6dffffffffffffffffffffffffffff16038411612b37576000612b4d565b888b6dffffffffffffffffffffffffffff160384035b9150878a6dffffffffffffffffffffffffffff16038311612b6f576000612b85565b878a6dffffffffffffffffffffffffffff160383035b90506000821180612b965750600081115b612c075760405162461bcd60e51b8152602060048201526024808201527f426c617a65537761703a20494e53554646494349454e545f494e5055545f414d60448201527f4f554e5400000000000000000000000000000000000000000000000000000000606482015260840161039c565b6000612c1483600361456b565b612c20866103e861456b565b612c2a9190614582565b90506000612c3983600361456b565b612c45866103e861456b565b612c4f9190614582565b9050612c6e6dffffffffffffffffffffffffffff808e16908f1661456b565b612c7b90620f424061456b565b612c85828461456b565b1015612cd35760405162461bcd60e51b815260206004820152600c60248201527f426c617a65537761703a204b0000000000000000000000000000000000000000604482015260640161039c565b5050612ce184848d8d6136ac565b60408051838152602081018390529081018a9052606081018990526001600160a01b0388169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a350505050610b2f60017f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399055565b600b5415610be457600080612dc76008546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b50915091506000846dffffffffffffffffffffffffffff16866dffffffffffffffffffffffffffff16612dfa919061456b565b612e176dffffffffffffffffffffffffffff80851690861661456b565b612e219190614582565b905080600c6000828254612e359190614931565b90915550508315612fc3576005546040517f88720d8c00000000000000000000000000000000000000000000000000000000815233600482015260009182916001600160a01b03909116906388720d8c906024016040805180830381865afa158015612ea5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ec99190614944565b90925090506001600160a01b03821615801590612ee65750600081115b15612603576000612710612efa838661456b565b612f0491906145dd565b905083156121a5576001600160a01b0383166000908152600d602052604081205490819003612f9157600e80546001810182556000919091527fbb7b4a454dc3493923482f07822329ed19e8244eff582cc204f8554c3620c3fd0180547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0386161790555b6001600160a01b0384166000908152600d602052604081208054849290612fb9908490614931565b9091555050505050505b505050505050565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b600080600560009054906101000a90046001600160a01b03166001600160a01b0316635ab7b6166040518163ffffffff1660e01b8152600401602060405180830381865afa158015613083573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130a791906147f5565b600b546001600160a01b03821615801594509192509061336357801561335e576004546000906001600160a01b031663677342ce6130f86dffffffffffffffffffffffffffff808916908a1661456b565b6040518263ffffffff1660e01b815260040161311691815260200190565b602060405180830381865afa158015613133573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131579190614595565b600480546040517f677342ce0000000000000000000000000000000000000000000000000000000081529182018590529192506000916001600160a01b03169063677342ce90602401602060405180830381865afa1580156131bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131e19190614595565b9050808211156133535760006131f78284614582565b600054613204919061456b565b905060008261321485600561456b565b61321e9190614931565b9050600061322c82846145dd565b9050801561334f5760005b600e5481101561333e576000600e828154811061325657613256614647565b600091825260208083209190910154600480546001600160a01b03928316808652600d909452604080862054600c5491517faa9a09120000000000000000000000000000000000000000000000000000000081529384018a90526024840152604483015292945091169063aa9a091290606401602060405180830381865afa1580156132e6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061330a9190614595565b905080156133295761331c82826135ff565b6133268185614582565b93505b5050808061333690614758565b915050613237565b50801561334f5761334f87826135ff565b5050505b61335b613bb2565b50505b613376565b8015613376576000600b55613376613bb2565b505092915050565b6001600160a01b0382166133d45760405162461bcd60e51b815260206004820152601760248201527f426c617a65537761703a205a45524f5f41444452455353000000000000000000604482015260640161039c565b6133df838383613c8a565b6001600160a01b03831660009081526001602052604081208054839290613407908490614582565b90915550506001600160a01b03821660009081526001602052604081208054839290613434908490614931565b92505081905550816001600160a01b0316836001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8360405161302091815260200190565b600080438411156134d35760405162461bcd60e51b815260206004820152601e60248201527f426c617a65537761703a20494e56414c49445f534e415053484f545f49440000604482015260640161039c565b82546000905b8082101561354257600060026134ef8385614931565b6134f991906145dd565b90508686828154811061350e5761350e614647565b906000526020600020906002020160000154111561352e5780915061353c565b613539816001614931565b92505b506134d9565b8454821061355257600080613579565b600185838154811061356657613566614647565b9060005260206000209060020201600101545b9350935050505b9250929050565b7f29b73ee8e70d5462b8b8ee06b237f7f69b80f34d018cb2c4a96f0e42cb33399080546002036135f95760405162461bcd60e51b815260206004820152601e60248201527f5265656e7472616e63794c6f636b3a207265656e7472616e742063616c6c0000604482015260640161039c565b60029055565b61360b60008383613c8a565b8060008082825461361c9190614931565b90915550506001600160a01b03821660009081526001602052604081208054839290613649908490614931565b90915550506040518181526001600160a01b038316906000907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020015b60405180910390a35050565b60008183106136a357816136a5565b825b9392505050565b6dffffffffffffffffffffffffffff84118015906136d857506dffffffffffffffffffffffffffff8311155b6137245760405162461bcd60e51b815260206004820152601360248201527f426c617a65537761703a204f564552464c4f5700000000000000000000000000604482015260640161039c565b60085463ffffffff428116917c01000000000000000000000000000000000000000000000000000000009004811682039081161580159061377457506dffffffffffffffffffffffffffff841615155b801561378f57506dffffffffffffffffffffffffffff831615155b156138715763ffffffff81166137e6856e0100000000000000000000000000006dffffffffffffffffffffffffffff8716025b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1690613d94565b600980547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff929092169290920201905563ffffffff8116613844846e0100000000000000000000000000006dffffffffffffffffffffffffffff8816026137c2565b600a80547bffffffffffffffffffffffffffffffffffffffffffffffffffffffff92909216929092020190555b506008805463ffffffff83167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff8881166e0100000000000000000000000000009081027fffffffff000000000000000000000000000000000000000000000000000000009095168b83161794909417918216831794859055604080519382169282169290921783529290930490911660208201527f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a15050505050565b61396d82600083613c8a565b6001600160a01b03821660009081526001602052604081208054839290613995908490614582565b92505081905550806000808282546139ad9190614582565b90915550506040518181526000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001613688565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691613a7a9190614520565b6000604051808303816000865af19150503d8060008114613ab7576040519150601f19603f3d011682016040523d82523d6000602084013e613abc565b606091505b5091509150818015613ae6575080511580613ae6575080806020019051810190613ae69190614972565b613b325760405162461bcd60e51b815260206004820152601c60248201527f5472616e7366657248656c7065723a3a736166655472616e7366657200000000604482015260640161039c565b5050505050565b337f52720094aed01ff34e348759e70383310167af8639ed3cc691bb00386db89cda546001600160a01b0316146127785760405162461bcd60e51b815260206004820152601960248201527f506172656e7452656c6174696f6e3a20464f5242494444454e00000000000000604482015260640161039c565b600e545b8015613c82576000600e613bcb600184614582565b81548110613bdb57613bdb614647565b60009182526020808320909101546001600160a01b0316808352600d9091526040822091909155600e80549192509080613c1757613c17614994565b60008281526020902081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690550190555080613c7a816149c3565b915050613bb6565b506000600c55565b613c95838383613ddb565b7fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f28547fed132e8732eaf2371e25ca93372ff1b0930f595119ad10a601cebe9034060f249015613d8e57600081600401600081548110613cf657613cf6614647565b60009182526020918290200154604080516001600160a01b0389811660248301528881166044830152606480830189905283518084039091018152608490920190925292830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f2f8358b600000000000000000000000000000000000000000000000000000000179052169150612fc39082906109a6565b50505050565b60006dffffffffffffffffffffffffffff82167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff841681613dd357613dd36145ae565b049392505050565b610be483836001600160a01b038216613e0357613df781613e28565b613dff613e56565b5050565b6001600160a01b038116613e1a57613df782613e28565b613e2382613e28565b613dff815b6001600160a01b0381166000908152600f60209081526040808320600190925290912054611e9d9190613e5f565b61277860106000545b815460009015613ea05782548390613e7990600190614582565b81548110613e8957613e89614647565b906000526020600020906002020160000154613ea3565b60005b905043811015610be45750604080518082019091524381526020808201928352835460018082018655600095865291909420915160029094029091019283559051910155565b7fffffffff0000000000000000000000000000000000000000000000000000000081168114611e9d57600080fd5b600060208284031215613f2957600080fd5b81356136a581613ee9565b6001600160a01b0381168114611e9d57600080fd5b600080600080600060808688031215613f6157600080fd5b85359450602086013593506040860135613f7a81613f34565b9250606086013567ffffffffffffffff80821115613f9757600080fd5b818801915088601f830112613fab57600080fd5b813581811115613fba57600080fd5b896020828501011115613fcc57600080fd5b9699959850939650602001949392505050565b60005b83811015613ffa578181015183820152602001613fe2565b50506000910152565b6000815180845261401b816020860160208601613fdf565b601f01601f19169290920160200192915050565b6020815260006136a56020830184614003565b6000806040838503121561405557600080fd5b823561406081613f34565b946020939093013593505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b60038110611e9d577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b602081016140e18361409d565b91905290565b6000806000606084860312156140fc57600080fd5b833561410781613f34565b9250602084013561411781613f34565b929592945050506040919091013590565b6020808252825182820181905260009190848201906040850190845b818110156141695783516001600160a01b031683529284019291840191600101614144565b50909695505050505050565b60006020828403121561418757600080fd5b81356136a581613f34565b600081518084526020808501945080840160005b838110156141e45781517fffffffff0000000000000000000000000000000000000000000000000000000016875295820195908201906001016141a6565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561427c578883037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc0018552815180516001600160a01b0316845287015187840187905261426987850182614192565b9588019593505090860190600101614216565b509098975050505050505050565b80356003811061134c57600080fd5b600080600080600060a086880312156142b157600080fd5b85356142bc81613f34565b945060208601356142cc81613f34565b935060408601356142dc81613f34565b92506142ea6060870161428a565b91506142f86080870161428a565b90509295509295909350565b60006020828403121561431657600080fd5b5035919050565b6000806020838503121561433057600080fd5b823567ffffffffffffffff8082111561434857600080fd5b818501915085601f83011261435c57600080fd5b81358181111561436b57600080fd5b8660208260051b850101111561438057600080fd5b60209290920196919550909350505050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015614405577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08886030184526143f3858351614003565b945092850192908501906001016143b9565b5092979650505050505050565b6020815260006136a56020830184614192565b60008060006060848603121561443a57600080fd5b833561444581613f34565b9250602084013561445581613f34565b9150604084013561446581613f34565b809150509250925092565b600080600080600080600060e0888a03121561448b57600080fd5b873561449681613f34565b965060208801356144a681613f34565b95506040880135945060608801359350608088013560ff811681146144ca57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600080604083850312156144fa57600080fd5b823561450581613f34565b9150602083013561451581613f34565b809150509250929050565b60008251614532818460208701613fdf565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082028115828204841417610a9157610a9161453c565b81810381811115610a9157610a9161453c565b6000602082840312156145a757600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614613577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b805161134c81613ee9565b6000806040838503121561469457600080fd5b825167ffffffffffffffff808211156146ac57600080fd5b818501915085601f8301126146c057600080fd5b81516020828211156146d4576146d4614618565b8160051b604051601f19603f830116810181811086821117156146f9576146f9614618565b60405292835281830193508481018201928984111561471757600080fd5b948201945b8386101561473c5761472d86614676565b8552948201949382019361471c565b965061474b9050878201614676565b9450505050509250929050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036147895761478961453c565b5060010190565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18436030181126147c557600080fd5b83018035915067ffffffffffffffff8211156147e057600080fd5b60200191503681900382131561358057600080fd5b60006020828403121561480757600080fd5b81516136a581613f34565b6000606080830181845280875180835260808601915060808160051b87010192506020808a0160005b838110156148b5577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8089870301855281516001600160a01b038151168752838101516148868161409d565b878501526040908101519087018890526148a288880182614192565b965050938201939082019060010161483b565b50506001600160a01b03891690870152505083810360408501526148d98186614003565b979650505050505050565b6001600160a01b038616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f909201601f19160101949350505050565b80820180821115610a9157610a9161453c565b6000806040838503121561495757600080fd5b825161496281613f34565b6020939093015192949293505050565b60006020828403121561498457600080fd5b815180151581146136a557600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b6000816149d2576149d261453c565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019056fea164736f6c6343000811000aa164736f6c6343000811000a