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