ETH Price: $3,812.64 (+5.39%)

Contract

0x4F0c01b41741f8022c6FB9Fe357Ea480184719D4
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Transaction Hash
Method
Block
From
To
Oft Send From212064162024-11-17 9:05:3517 days ago1731834335IN
0x4F0c01b4...0184719D4
0.00050804 ETH0.002359389.31385727
Oft Send From211508182024-11-09 14:53:1125 days ago1731163991IN
0x4F0c01b4...0184719D4
0.00062798 ETH0.0038944413.54976527
Oft Send From210414242024-10-25 8:26:2340 days ago1729844783IN
0x4F0c01b4...0184719D4
0.00061064 ETH0.002107828.32079669
Oft Send From209664362024-10-14 21:17:3551 days ago1728940655IN
0x4F0c01b4...0184719D4
0.00057486 ETH0.0045484315.71035522
Oft Send From209567142024-10-13 12:41:2352 days ago1728823283IN
0x4F0c01b4...0184719D4
0.00061113 ETH0.004204614.52278375
Oft Send From209523142024-10-12 21:50:2353 days ago1728769823IN
0x4F0c01b4...0184719D4
0.00061071 ETH0.002248297.76566092
Oft Send From209390532024-10-11 1:19:1154 days ago1728609551IN
0x4F0c01b4...0184719D4
0.00061785 ETH0.002460688.36097582
Oft Send From209329992024-10-10 5:04:3555 days ago1728536675IN
0x4F0c01b4...0184719D4
0.00061711 ETH0.0026328.94237382
Oft Send From209054522024-10-06 8:55:2359 days ago1728204923IN
0x4F0c01b4...0184719D4
0.0006039 ETH0.002561748.92301448
Oft Send From209051092024-10-06 7:46:2359 days ago1728200783IN
0x4F0c01b4...0184719D4
0.00066043 ETH0.001370394.77261838
Oft Send From208933252024-10-04 16:21:5961 days ago1728058919IN
0x4F0c01b4...0184719D4
0.00061488 ETH0.0050393617.12216599
Oft Send From208905112024-10-04 6:57:4761 days ago1728025067IN
0x4F0c01b4...0184719D4
0.00061802 ETH0.001646055.59255727
Lzv2oft Send208744782024-10-02 1:18:4763 days ago1727831927IN
0x4F0c01b4...0184719D4
0.00039501 ETH0.001773245.28054195
Lzv2oft Send208632452024-09-30 11:43:2365 days ago1727696603IN
0x4F0c01b4...0184719D4
0.00037325 ETH0.003070178.8321473
Oft Send From208573472024-09-29 15:59:2366 days ago1727625563IN
0x4F0c01b4...0184719D4
0.00057176 ETH0.002143557.28313362
Oft Send From208572612024-09-29 15:41:5966 days ago1727624519IN
0x4F0c01b4...0184719D4
0.00057176 ETH0.002171237.3774791
Oft Send From208536422024-09-29 3:35:1166 days ago1727580911IN
0x4F0c01b4...0184719D4
0.00057149 ETH0.001730855.88114298
Oft Send From208490152024-09-28 12:04:2367 days ago1727525063IN
0x4F0c01b4...0184719D4
0.00057116 ETH0.001854376.30031274
Oft Send From208440112024-09-27 19:20:1168 days ago1727464811IN
0x4F0c01b4...0184719D4
0.00055894 ETH0.0089287931.10059646
Oft Send From208326702024-09-26 5:23:2369 days ago1727328203IN
0x4F0c01b4...0184719D4
0.00060257 ETH0.0034710913.44634961
Lzv2oft Send208162562024-09-23 22:25:5972 days ago1727130359IN
0x4F0c01b4...0184719D4
0.0003639 ETH0.0049485514.32108514
Oft Send From208088372024-09-22 21:34:3573 days ago1727040875IN
0x4F0c01b4...0184719D4
0.00055996 ETH0.002499658.6472454
Oft Send From208082722024-09-22 19:40:5973 days ago1727034059IN
0x4F0c01b4...0184719D4
0.00056834 ETH0.002687269.4383304
Oft Send From208048352024-09-22 8:10:4773 days ago1726992647IN
0x4F0c01b4...0184719D4
0.0005668 ETH0.0032080610.9
Lzv2oft Send208032002024-09-22 2:42:4773 days ago1726972967IN
0x4F0c01b4...0184719D4
0.00036489 ETH0.002006855.89482453
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
212064162024-11-17 9:05:3517 days ago1731834335
0x4F0c01b4...0184719D4
0.0001586 ETH
212064162024-11-17 9:05:3517 days ago1731834335
0x4F0c01b4...0184719D4
0.00034944 ETH
211508182024-11-09 14:53:1125 days ago1731163991
0x4F0c01b4...0184719D4
0.00016444 ETH
211508182024-11-09 14:53:1125 days ago1731163991
0x4F0c01b4...0184719D4
0.00046353 ETH
210414242024-10-25 8:26:2340 days ago1729844783
0x4F0c01b4...0184719D4
0.0002008 ETH
210414242024-10-25 8:26:2340 days ago1729844783
0x4F0c01b4...0184719D4
0.00040984 ETH
209664362024-10-14 21:17:3551 days ago1728940655
0x4F0c01b4...0184719D4
0.00019052 ETH
209664362024-10-14 21:17:3551 days ago1728940655
0x4F0c01b4...0184719D4
0.00038434 ETH
209567142024-10-13 12:41:2352 days ago1728823283
0x4F0c01b4...0184719D4
0.00020285 ETH
209567142024-10-13 12:41:2352 days ago1728823283
0x4F0c01b4...0184719D4
0.00040828 ETH
209523142024-10-12 21:50:2353 days ago1728769823
0x4F0c01b4...0184719D4
0.00020243 ETH
209523142024-10-12 21:50:2353 days ago1728769823
0x4F0c01b4...0184719D4
0.00040828 ETH
209390532024-10-11 1:19:1154 days ago1728609551
0x4F0c01b4...0184719D4
0.00020957 ETH
209390532024-10-11 1:19:1154 days ago1728609551
0x4F0c01b4...0184719D4
0.00040828 ETH
209329992024-10-10 5:04:3555 days ago1728536675
0x4F0c01b4...0184719D4
0.00020882 ETH
209329992024-10-10 5:04:3555 days ago1728536675
0x4F0c01b4...0184719D4
0.00040828 ETH
209054522024-10-06 8:55:2359 days ago1728204923
0x4F0c01b4...0184719D4
0.0002062 ETH
209054522024-10-06 8:55:2359 days ago1728204923
0x4F0c01b4...0184719D4
0.0003977 ETH
209051092024-10-06 7:46:2359 days ago1728200783
0x4F0c01b4...0184719D4
0.00020674 ETH
209051092024-10-06 7:46:2359 days ago1728200783
0x4F0c01b4...0184719D4
0.00045368 ETH
208933252024-10-04 16:21:5961 days ago1728058919
0x4F0c01b4...0184719D4
0.0002066 ETH
208933252024-10-04 16:21:5961 days ago1728058919
0x4F0c01b4...0184719D4
0.00040828 ETH
208905112024-10-04 6:57:4761 days ago1728025067
0x4F0c01b4...0184719D4
0.00020974 ETH
208905112024-10-04 6:57:4761 days ago1728025067
0x4F0c01b4...0184719D4
0.00040828 ETH
208744782024-10-02 1:18:4763 days ago1727831927
0x4F0c01b4...0184719D4
0.00020306 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
OFTWrapperDiamond

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 49 : OFTWrapperDiamond.sol
// SPDX-License-Identifier: AGPL-3.0-only

pragma solidity 0.8.19;

import { SolidStateDiamond } from '@solidstate/contracts/proxy/diamond/SolidStateDiamond.sol';
import { IPausable } from '@solidstate/contracts/security/pausable/IPausable.sol';
import { Pausable } from '@solidstate/contracts/security/pausable/Pausable.sol';
import { ReentrancyGuard } from '@solidstate/contracts/security/reentrancy_guard/ReentrancyGuard.sol';
import { ITokenBalance } from '../../interfaces/ITokenBalance.sol';
import { OFTWrapperStorage } from './OFTWrapperStorage.sol';
import '../../helpers/TransferHelper.sol' as TransferHelper;
import '../../Constants.sol' as Constants;

/**
 * @title OFTWrapperDiamond
 * @notice The OFT wrapper diamond contract
 */
contract OFTWrapperDiamond is SolidStateDiamond, Pausable, ReentrancyGuard {
    /**
     * @notice Emitted when the address of the collector is set
     * @param collector The address of the collector
     */
    event SetCollector(address indexed collector);

    uint256 private constant SYSTEM_VERSION_ID_INTERNAL = uint256(keccak256('Initial'));

    /**
     * @notice Initializes the contract
     * @param _collector The initial address of the collector
     * @param _owner The address of the initial owner of the contract
     */
    constructor(address _collector, address _owner) {
        _initOFTWrapperDiamond();

        _setCollector(_collector);

        if (_owner != msg.sender && _owner != address(0)) {
            _setOwner(_owner);
        }
    }

    /**
     * @notice Sets the address of the collector
     * @param _collector The address of the collector
     */
    function setCollector(address _collector) external onlyOwner {
        _setCollector(_collector);
    }

    /**
     * @notice Enter pause state
     */
    function pause() external onlyOwner whenNotPaused {
        _pause();
    }

    /**
     * @notice Exit pause state
     */
    function unpause() external onlyOwner whenPaused {
        _unpause();
    }

    /**
     * @notice Transfers ownership of the contract to a new account
     * @dev Can only be called by the current owner
     * @param _newOwner The address of the contract owner
     */
    function forceTransferOwnership(address _newOwner) external onlyOwner {
        _setOwner(_newOwner);
    }

    /**
     * @notice Performs the token cleanup
     * @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token
     * @param _tokenAddress The address of the token
     */
    function cleanup(address _tokenAddress) external onlyOwner {
        if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
            TransferHelper.safeTransferNative(msg.sender, address(this).balance);
        } else {
            TransferHelper.safeTransfer(
                _tokenAddress,
                msg.sender,
                ITokenBalance(_tokenAddress).balanceOf(address(this))
            );
        }
    }

    /**
     * @notice Performs the token cleanup using the provided amount
     * @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token
     * @param _tokenAddress The address of the token
     * @param _tokenAmount The amount of the token
     */
    function cleanupWithAmount(address _tokenAddress, uint256 _tokenAmount) external onlyOwner {
        if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
            TransferHelper.safeTransferNative(msg.sender, _tokenAmount);
        } else {
            TransferHelper.safeTransfer(_tokenAddress, msg.sender, _tokenAmount);
        }
    }

    /**
     * @notice Getter of the token balance of the current contract
     * @dev Use the "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE" address for the native token
     * @param _tokenAddress The address of the token
     * @return The token balance of the current contract
     */
    function tokenBalance(address _tokenAddress) external view returns (uint256) {
        if (_tokenAddress == Constants.NATIVE_TOKEN_ADDRESS) {
            return address(this).balance;
        } else {
            return ITokenBalance(_tokenAddress).balanceOf(address(this));
        }
    }

    /**
     * @notice Getter of the address of the collector
     * @return The address of the collector
     */
    function collector() external view returns (address) {
        return OFTWrapperStorage.layout().collector;
    }

    /**
     * @notice Getter of the system version identifier
     * @return The system version identifier
     */
    function SYSTEM_VERSION_ID() external pure returns (uint256) {
        return SYSTEM_VERSION_ID_INTERNAL;
    }

    function _setCollector(address _collector) private {
        OFTWrapperStorage.layout().collector = _collector;

        emit SetCollector(_collector);
    }

    function _initOFTWrapperDiamond() private {
        bytes4[] memory selectors = new bytes4[](10);
        uint256 selectorIndex;

        // register Pausable

        selectors[selectorIndex++] = IPausable.paused.selector;

        _setSupportsInterface(type(IPausable).interfaceId, true);

        // register collector functions

        selectors[selectorIndex++] = OFTWrapperDiamond.setCollector.selector;
        selectors[selectorIndex++] = OFTWrapperDiamond.collector.selector;

        // register service functions

        selectors[selectorIndex++] = OFTWrapperDiamond.pause.selector;
        selectors[selectorIndex++] = OFTWrapperDiamond.unpause.selector;
        selectors[selectorIndex++] = OFTWrapperDiamond.forceTransferOwnership.selector;
        selectors[selectorIndex++] = OFTWrapperDiamond.cleanup.selector;
        selectors[selectorIndex++] = OFTWrapperDiamond.cleanupWithAmount.selector;
        selectors[selectorIndex++] = OFTWrapperDiamond.tokenBalance.selector;
        selectors[selectorIndex++] = OFTWrapperDiamond.SYSTEM_VERSION_ID.selector;

        // diamond cut

        FacetCut[] memory facetCuts = new FacetCut[](1);

        facetCuts[0] = FacetCut({
            target: address(this),
            action: FacetCutAction.ADD,
            selectors: selectors
        });

        _diamondCut(facetCuts, address(0), '');
    }
}

File 2 of 49 : IOwnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC173 } from '../../interfaces/IERC173.sol';
import { IOwnableInternal } from './IOwnableInternal.sol';

interface IOwnable is IOwnableInternal, IERC173 {}

File 3 of 49 : IOwnableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC173Internal } from '../../interfaces/IERC173Internal.sol';

interface IOwnableInternal is IERC173Internal {
    error Ownable__NotOwner();
    error Ownable__NotTransitiveOwner();
}

File 4 of 49 : ISafeOwnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IOwnable } from './IOwnable.sol';
import { ISafeOwnableInternal } from './ISafeOwnableInternal.sol';

interface ISafeOwnable is ISafeOwnableInternal, IOwnable {
    /**
     * @notice get the nominated owner who has permission to call acceptOwnership
     */
    function nomineeOwner() external view returns (address);

    /**
     * @notice accept transfer of contract ownership
     */
    function acceptOwnership() external;
}

File 5 of 49 : ISafeOwnableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IOwnableInternal } from './IOwnableInternal.sol';

interface ISafeOwnableInternal is IOwnableInternal {
    error SafeOwnable__NotNomineeOwner();
}

File 6 of 49 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC173 } from '../../interfaces/IERC173.sol';
import { IOwnable } from './IOwnable.sol';
import { OwnableInternal } from './OwnableInternal.sol';

/**
 * @title Ownership access control based on ERC173
 */
abstract contract Ownable is IOwnable, OwnableInternal {
    /**
     * @inheritdoc IERC173
     */
    function owner() public view virtual returns (address) {
        return _owner();
    }

    /**
     * @inheritdoc IERC173
     */
    function transferOwnership(address account) public virtual onlyOwner {
        _transferOwnership(account);
    }
}

File 7 of 49 : OwnableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC173 } from '../../interfaces/IERC173.sol';
import { AddressUtils } from '../../utils/AddressUtils.sol';
import { IOwnableInternal } from './IOwnableInternal.sol';
import { OwnableStorage } from './OwnableStorage.sol';

abstract contract OwnableInternal is IOwnableInternal {
    using AddressUtils for address;

    modifier onlyOwner() {
        if (msg.sender != _owner()) revert Ownable__NotOwner();
        _;
    }

    modifier onlyTransitiveOwner() {
        if (msg.sender != _transitiveOwner())
            revert Ownable__NotTransitiveOwner();
        _;
    }

    function _owner() internal view virtual returns (address) {
        return OwnableStorage.layout().owner;
    }

    function _transitiveOwner() internal view virtual returns (address owner) {
        owner = _owner();

        while (owner.isContract()) {
            try IERC173(owner).owner() returns (address transitiveOwner) {
                owner = transitiveOwner;
            } catch {
                break;
            }
        }
    }

    function _transferOwnership(address account) internal virtual {
        _setOwner(account);
    }

    function _setOwner(address account) internal virtual {
        OwnableStorage.Layout storage l = OwnableStorage.layout();
        emit OwnershipTransferred(l.owner, account);
        l.owner = account;
    }
}

File 8 of 49 : OwnableStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

library OwnableStorage {
    struct Layout {
        address owner;
    }

    bytes32 internal constant STORAGE_SLOT =
        keccak256('solidstate.contracts.storage.Ownable');

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

File 9 of 49 : SafeOwnable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { Ownable } from './Ownable.sol';
import { ISafeOwnable } from './ISafeOwnable.sol';
import { OwnableInternal } from './OwnableInternal.sol';
import { SafeOwnableInternal } from './SafeOwnableInternal.sol';

/**
 * @title Ownership access control based on ERC173 with ownership transfer safety check
 */
abstract contract SafeOwnable is ISafeOwnable, Ownable, SafeOwnableInternal {
    /**
     * @inheritdoc ISafeOwnable
     */
    function nomineeOwner() public view virtual returns (address) {
        return _nomineeOwner();
    }

    /**
     * @inheritdoc ISafeOwnable
     */
    function acceptOwnership() public virtual onlyNomineeOwner {
        _acceptOwnership();
    }

    function _transferOwnership(
        address account
    ) internal virtual override(OwnableInternal, SafeOwnableInternal) {
        super._transferOwnership(account);
    }
}

File 10 of 49 : SafeOwnableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { ISafeOwnableInternal } from './ISafeOwnableInternal.sol';
import { OwnableInternal } from './OwnableInternal.sol';
import { SafeOwnableStorage } from './SafeOwnableStorage.sol';

abstract contract SafeOwnableInternal is ISafeOwnableInternal, OwnableInternal {
    modifier onlyNomineeOwner() {
        if (msg.sender != _nomineeOwner())
            revert SafeOwnable__NotNomineeOwner();
        _;
    }

    /**
     * @notice get the nominated owner who has permission to call acceptOwnership
     */
    function _nomineeOwner() internal view virtual returns (address) {
        return SafeOwnableStorage.layout().nomineeOwner;
    }

    /**
     * @notice accept transfer of contract ownership
     */
    function _acceptOwnership() internal virtual {
        _setOwner(msg.sender);
        delete SafeOwnableStorage.layout().nomineeOwner;
    }

    /**
     * @notice grant permission to given address to claim contract ownership
     */
    function _transferOwnership(address account) internal virtual override {
        _setNomineeOwner(account);
    }

    /**
     * @notice set nominee owner
     */
    function _setNomineeOwner(address account) internal virtual {
        SafeOwnableStorage.layout().nomineeOwner = account;
    }
}

File 11 of 49 : SafeOwnableStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

library SafeOwnableStorage {
    struct Layout {
        address nomineeOwner;
    }

    bytes32 internal constant STORAGE_SLOT =
        keccak256('solidstate.contracts.storage.SafeOwnable');

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

File 12 of 49 : IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC165Internal } from './IERC165Internal.sol';

/**
 * @title ERC165 interface registration interface
 * @dev see https://eips.ethereum.org/EIPS/eip-165
 */
interface IERC165 is IERC165Internal {
    /**
     * @notice query whether contract has registered support for given interface
     * @param interfaceId interface id
     * @return bool whether interface is supported
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 13 of 49 : IERC165Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title ERC165 interface registration interface
 */
interface IERC165Internal {

}

File 14 of 49 : IERC173.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC173Internal } from './IERC173Internal.sol';

/**
 * @title Contract ownership standard interface
 * @dev see https://eips.ethereum.org/EIPS/eip-173
 */
interface IERC173 is IERC173Internal {
    /**
     * @notice get the ERC173 contract owner
     * @return contract owner
     */
    function owner() external view returns (address);

    /**
     * @notice transfer contract ownership to new account
     * @param account address of new owner
     */
    function transferOwnership(address account) external;
}

File 15 of 49 : IERC173Internal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title Partial ERC173 interface needed by internal functions
 */
interface IERC173Internal {
    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );
}

File 16 of 49 : ERC165Base.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC165 } from '../../../interfaces/IERC165.sol';
import { IERC165Base } from './IERC165Base.sol';
import { ERC165BaseInternal } from './ERC165BaseInternal.sol';
import { ERC165BaseStorage } from './ERC165BaseStorage.sol';

/**
 * @title ERC165 implementation
 */
abstract contract ERC165Base is IERC165Base, ERC165BaseInternal {
    /**
     * @inheritdoc IERC165
     */
    function supportsInterface(bytes4 interfaceId) public view returns (bool) {
        return _supportsInterface(interfaceId);
    }
}

File 17 of 49 : ERC165BaseInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IERC165BaseInternal } from './IERC165BaseInternal.sol';
import { ERC165BaseStorage } from './ERC165BaseStorage.sol';

/**
 * @title ERC165 implementation
 */
abstract contract ERC165BaseInternal is IERC165BaseInternal {
    /**
     * @notice indicates whether an interface is already supported based on the interfaceId
     * @param interfaceId id of interface to check
     * @return bool indicating whether interface is supported
     */
    function _supportsInterface(
        bytes4 interfaceId
    ) internal view virtual returns (bool) {
        return ERC165BaseStorage.layout().supportedInterfaces[interfaceId];
    }

    /**
     * @notice sets status of interface support
     * @param interfaceId id of interface to set status for
     * @param status boolean indicating whether interface will be set as supported
     */
    function _setSupportsInterface(
        bytes4 interfaceId,
        bool status
    ) internal virtual {
        if (interfaceId == 0xffffffff) revert ERC165Base__InvalidInterfaceId();
        ERC165BaseStorage.layout().supportedInterfaces[interfaceId] = status;
    }
}

File 18 of 49 : ERC165BaseStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

library ERC165BaseStorage {
    struct Layout {
        mapping(bytes4 => bool) supportedInterfaces;
    }

    bytes32 internal constant STORAGE_SLOT =
        keccak256('solidstate.contracts.storage.ERC165Base');

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

File 19 of 49 : IERC165Base.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC165 } from '../../../interfaces/IERC165.sol';
import { IERC165BaseInternal } from './IERC165BaseInternal.sol';

interface IERC165Base is IERC165, IERC165BaseInternal {}

File 20 of 49 : IERC165BaseInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { IERC165Internal } from '../../../interfaces/IERC165Internal.sol';

interface IERC165BaseInternal is IERC165Internal {
    error ERC165Base__InvalidInterfaceId();
}

File 21 of 49 : DiamondBase.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { Proxy } from '../../Proxy.sol';
import { IDiamondBase } from './IDiamondBase.sol';
import { DiamondBaseStorage } from './DiamondBaseStorage.sol';

/**
 * @title EIP-2535 "Diamond" proxy base contract
 * @dev see https://eips.ethereum.org/EIPS/eip-2535
 */
abstract contract DiamondBase is IDiamondBase, Proxy {
    /**
     * @inheritdoc Proxy
     */
    function _getImplementation()
        internal
        view
        virtual
        override
        returns (address implementation)
    {
        // inline storage layout retrieval uses less gas
        DiamondBaseStorage.Layout storage l;
        bytes32 slot = DiamondBaseStorage.STORAGE_SLOT;
        assembly {
            l.slot := slot
        }

        implementation = address(bytes20(l.facets[msg.sig]));
    }
}

File 22 of 49 : DiamondBaseStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @dev derived from https://github.com/mudgen/diamond-2 (MIT license)
 */
library DiamondBaseStorage {
    struct Layout {
        // function selector => (facet address, selector slot position)
        mapping(bytes4 => bytes32) facets;
        // total number of selectors registered
        uint16 selectorCount;
        // array of selector slots with 8 selectors per slot
        mapping(uint256 => bytes32) selectorSlots;
        address fallbackAddress;
    }

    bytes32 internal constant STORAGE_SLOT =
        keccak256('solidstate.contracts.storage.DiamondBase');

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

File 23 of 49 : IDiamondBase.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IProxy } from '../../IProxy.sol';

interface IDiamondBase is IProxy {}

File 24 of 49 : DiamondFallback.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { OwnableInternal } from '../../../access/ownable/OwnableInternal.sol';
import { DiamondBase } from '../base/DiamondBase.sol';
import { DiamondBaseStorage } from '../base/DiamondBaseStorage.sol';
import { IDiamondFallback } from './IDiamondFallback.sol';

/**
 * @title Fallback feature for EIP-2535 "Diamond" proxy
 */
abstract contract DiamondFallback is
    IDiamondFallback,
    OwnableInternal,
    DiamondBase
{
    /**
     * @inheritdoc IDiamondFallback
     */
    function getFallbackAddress()
        external
        view
        returns (address fallbackAddress)
    {
        fallbackAddress = _getFallbackAddress();
    }

    /**
     * @inheritdoc IDiamondFallback
     */
    function setFallbackAddress(address fallbackAddress) external onlyOwner {
        _setFallbackAddress(fallbackAddress);
    }

    /**
     * @inheritdoc DiamondBase
     * @notice query custom fallback address is no implementation is found
     */
    function _getImplementation()
        internal
        view
        virtual
        override
        returns (address implementation)
    {
        implementation = super._getImplementation();

        if (implementation == address(0)) {
            implementation = _getFallbackAddress();
        }
    }

    /**
     * @notice query the address of the fallback implementation
     * @return fallbackAddress address of fallback implementation
     */
    function _getFallbackAddress()
        internal
        view
        virtual
        returns (address fallbackAddress)
    {
        fallbackAddress = DiamondBaseStorage.layout().fallbackAddress;
    }

    /**
     * @notice set the address of the fallback implementation
     * @param fallbackAddress address of fallback implementation
     */
    function _setFallbackAddress(address fallbackAddress) internal virtual {
        DiamondBaseStorage.layout().fallbackAddress = fallbackAddress;
    }
}

File 25 of 49 : IDiamondFallback.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IDiamondBase } from '../base/IDiamondBase.sol';

interface IDiamondFallback is IDiamondBase {
    /**
     * @notice query the address of the fallback implementation
     * @return fallbackAddress address of fallback implementation
     */
    function getFallbackAddress()
        external
        view
        returns (address fallbackAddress);

    /**
     * @notice set the address of the fallback implementation
     * @param fallbackAddress address of fallback implementation
     */
    function setFallbackAddress(address fallbackAddress) external;
}

File 26 of 49 : ISolidStateDiamond.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { ISafeOwnable } from '../../access/ownable/ISafeOwnable.sol';
import { IERC165 } from '../../interfaces/IERC165.sol';
import { IDiamondBase } from './base/IDiamondBase.sol';
import { IDiamondFallback } from './fallback/IDiamondFallback.sol';
import { IDiamondReadable } from './readable/IDiamondReadable.sol';
import { IDiamondWritable } from './writable/IDiamondWritable.sol';

interface ISolidStateDiamond is
    IDiamondBase,
    IDiamondFallback,
    IDiamondReadable,
    IDiamondWritable,
    ISafeOwnable,
    IERC165
{
    receive() external payable;
}

File 27 of 49 : DiamondReadable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { DiamondBaseStorage } from '../base/DiamondBaseStorage.sol';
import { IDiamondReadable } from './IDiamondReadable.sol';

/**
 * @title EIP-2535 "Diamond" proxy introspection contract
 * @dev derived from https://github.com/mudgen/diamond-2 (MIT license)
 */
abstract contract DiamondReadable is IDiamondReadable {
    /**
     * @inheritdoc IDiamondReadable
     */
    function facets() external view returns (Facet[] memory diamondFacets) {
        DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();

        diamondFacets = new Facet[](l.selectorCount);

        uint8[] memory numFacetSelectors = new uint8[](l.selectorCount);
        uint256 numFacets;
        uint256 selectorIndex;

        // loop through function selectors
        for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
            bytes32 slot = l.selectorSlots[slotIndex];

            for (
                uint256 selectorSlotIndex;
                selectorSlotIndex < 8;
                selectorSlotIndex++
            ) {
                selectorIndex++;

                if (selectorIndex > l.selectorCount) {
                    break;
                }

                bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));
                address facet = address(bytes20(l.facets[selector]));

                bool continueLoop;

                for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
                    if (diamondFacets[facetIndex].target == facet) {
                        diamondFacets[facetIndex].selectors[
                            numFacetSelectors[facetIndex]
                        ] = selector;
                        // probably will never have more than 256 functions from one facet contract
                        require(numFacetSelectors[facetIndex] < 255);
                        numFacetSelectors[facetIndex]++;
                        continueLoop = true;
                        break;
                    }
                }

                if (continueLoop) {
                    continue;
                }

                diamondFacets[numFacets].target = facet;
                diamondFacets[numFacets].selectors = new bytes4[](
                    l.selectorCount
                );
                diamondFacets[numFacets].selectors[0] = selector;
                numFacetSelectors[numFacets] = 1;
                numFacets++;
            }
        }

        for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
            uint256 numSelectors = numFacetSelectors[facetIndex];
            bytes4[] memory selectors = diamondFacets[facetIndex].selectors;

            // setting the number of selectors
            assembly {
                mstore(selectors, numSelectors)
            }
        }

        // setting the number of facets
        assembly {
            mstore(diamondFacets, numFacets)
        }
    }

    /**
     * @inheritdoc IDiamondReadable
     */
    function facetFunctionSelectors(
        address facet
    ) external view returns (bytes4[] memory selectors) {
        DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();

        selectors = new bytes4[](l.selectorCount);

        uint256 numSelectors;
        uint256 selectorIndex;

        // loop through function selectors
        for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
            bytes32 slot = l.selectorSlots[slotIndex];

            for (
                uint256 selectorSlotIndex;
                selectorSlotIndex < 8;
                selectorSlotIndex++
            ) {
                selectorIndex++;

                if (selectorIndex > l.selectorCount) {
                    break;
                }

                bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));

                if (facet == address(bytes20(l.facets[selector]))) {
                    selectors[numSelectors] = selector;
                    numSelectors++;
                }
            }
        }

        // set the number of selectors in the array
        assembly {
            mstore(selectors, numSelectors)
        }
    }

    /**
     * @inheritdoc IDiamondReadable
     */
    function facetAddresses()
        external
        view
        returns (address[] memory addresses)
    {
        DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();

        addresses = new address[](l.selectorCount);
        uint256 numFacets;
        uint256 selectorIndex;

        for (uint256 slotIndex; selectorIndex < l.selectorCount; slotIndex++) {
            bytes32 slot = l.selectorSlots[slotIndex];

            for (
                uint256 selectorSlotIndex;
                selectorSlotIndex < 8;
                selectorSlotIndex++
            ) {
                selectorIndex++;

                if (selectorIndex > l.selectorCount) {
                    break;
                }

                bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));
                address facet = address(bytes20(l.facets[selector]));

                bool continueLoop;

                for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {
                    if (facet == addresses[facetIndex]) {
                        continueLoop = true;
                        break;
                    }
                }

                if (continueLoop) {
                    continue;
                }

                addresses[numFacets] = facet;
                numFacets++;
            }
        }

        // set the number of facet addresses in the array
        assembly {
            mstore(addresses, numFacets)
        }
    }

    /**
     * @inheritdoc IDiamondReadable
     */
    function facetAddress(
        bytes4 selector
    ) external view returns (address facet) {
        facet = address(bytes20(DiamondBaseStorage.layout().facets[selector]));
    }
}

File 28 of 49 : IDiamondReadable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title Diamond proxy introspection interface
 * @dev see https://eips.ethereum.org/EIPS/eip-2535
 */
interface IDiamondReadable {
    struct Facet {
        address target;
        bytes4[] selectors;
    }

    /**
     * @notice get all facets and their selectors
     * @return diamondFacets array of structured facet data
     */
    function facets() external view returns (Facet[] memory diamondFacets);

    /**
     * @notice get all selectors for given facet address
     * @param facet address of facet to query
     * @return selectors array of function selectors
     */
    function facetFunctionSelectors(
        address facet
    ) external view returns (bytes4[] memory selectors);

    /**
     * @notice get addresses of all facets used by diamond
     * @return addresses array of facet addresses
     */
    function facetAddresses()
        external
        view
        returns (address[] memory addresses);

    /**
     * @notice get the address of the facet associated with given selector
     * @param selector function selector to query
     * @return facet facet address (zero address if not found)
     */
    function facetAddress(
        bytes4 selector
    ) external view returns (address facet);
}

File 29 of 49 : SolidStateDiamond.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IOwnable, Ownable, OwnableInternal } from '../../access/ownable/Ownable.sol';
import { ISafeOwnable, SafeOwnable } from '../../access/ownable/SafeOwnable.sol';
import { IERC165 } from '../../interfaces/IERC165.sol';
import { IERC173 } from '../../interfaces/IERC173.sol';
import { ERC165Base, ERC165BaseStorage } from '../../introspection/ERC165/base/ERC165Base.sol';
import { DiamondBase } from './base/DiamondBase.sol';
import { DiamondFallback, IDiamondFallback } from './fallback/DiamondFallback.sol';
import { DiamondReadable, IDiamondReadable } from './readable/DiamondReadable.sol';
import { DiamondWritable, IDiamondWritable } from './writable/DiamondWritable.sol';
import { ISolidStateDiamond } from './ISolidStateDiamond.sol';

/**
 * @title SolidState "Diamond" proxy reference implementation
 */
abstract contract SolidStateDiamond is
    ISolidStateDiamond,
    DiamondBase,
    DiamondFallback,
    DiamondReadable,
    DiamondWritable,
    SafeOwnable,
    ERC165Base
{
    constructor() {
        bytes4[] memory selectors = new bytes4[](12);
        uint256 selectorIndex;

        // register DiamondFallback

        selectors[selectorIndex++] = IDiamondFallback
            .getFallbackAddress
            .selector;
        selectors[selectorIndex++] = IDiamondFallback
            .setFallbackAddress
            .selector;

        _setSupportsInterface(type(IDiamondFallback).interfaceId, true);

        // register DiamondWritable

        selectors[selectorIndex++] = IDiamondWritable.diamondCut.selector;

        _setSupportsInterface(type(IDiamondWritable).interfaceId, true);

        // register DiamondReadable

        selectors[selectorIndex++] = IDiamondReadable.facets.selector;
        selectors[selectorIndex++] = IDiamondReadable
            .facetFunctionSelectors
            .selector;
        selectors[selectorIndex++] = IDiamondReadable.facetAddresses.selector;
        selectors[selectorIndex++] = IDiamondReadable.facetAddress.selector;

        _setSupportsInterface(type(IDiamondReadable).interfaceId, true);

        // register ERC165

        selectors[selectorIndex++] = IERC165.supportsInterface.selector;

        _setSupportsInterface(type(IERC165).interfaceId, true);

        // register SafeOwnable

        selectors[selectorIndex++] = Ownable.owner.selector;
        selectors[selectorIndex++] = SafeOwnable.nomineeOwner.selector;
        selectors[selectorIndex++] = Ownable.transferOwnership.selector;
        selectors[selectorIndex++] = SafeOwnable.acceptOwnership.selector;

        _setSupportsInterface(type(IERC173).interfaceId, true);

        // diamond cut

        FacetCut[] memory facetCuts = new FacetCut[](1);

        facetCuts[0] = FacetCut({
            target: address(this),
            action: FacetCutAction.ADD,
            selectors: selectors
        });

        _diamondCut(facetCuts, address(0), '');

        // set owner

        _setOwner(msg.sender);
    }

    receive() external payable {}

    function _transferOwnership(
        address account
    ) internal virtual override(OwnableInternal, SafeOwnable) {
        super._transferOwnership(account);
    }

    /**
     * @inheritdoc DiamondFallback
     */
    function _getImplementation()
        internal
        view
        override(DiamondBase, DiamondFallback)
        returns (address implementation)
    {
        implementation = super._getImplementation();
    }
}

File 30 of 49 : DiamondWritable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { OwnableInternal } from '../../../access/ownable/OwnableInternal.sol';
import { IDiamondWritable } from './IDiamondWritable.sol';
import { DiamondWritableInternal } from './DiamondWritableInternal.sol';

/**
 * @title EIP-2535 "Diamond" proxy update contract
 */
abstract contract DiamondWritable is
    IDiamondWritable,
    DiamondWritableInternal,
    OwnableInternal
{
    /**
     * @inheritdoc IDiamondWritable
     */
    function diamondCut(
        FacetCut[] calldata facetCuts,
        address target,
        bytes calldata data
    ) external onlyOwner {
        _diamondCut(facetCuts, target, data);
    }
}

File 31 of 49 : DiamondWritableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import { AddressUtils } from '../../../utils/AddressUtils.sol';
import { DiamondBaseStorage } from '../base/DiamondBaseStorage.sol';
import { IDiamondWritableInternal } from './IDiamondWritableInternal.sol';

abstract contract DiamondWritableInternal is IDiamondWritableInternal {
    using AddressUtils for address;

    bytes32 private constant CLEAR_ADDRESS_MASK =
        bytes32(uint256(0xffffffffffffffffffffffff));
    bytes32 private constant CLEAR_SELECTOR_MASK =
        bytes32(uint256(0xffffffff << 224));

    /**
     * @notice update functions callable on Diamond proxy
     * @param facetCuts array of structured Diamond facet update data
     * @param target optional recipient of initialization delegatecall
     * @param data optional initialization call data
     */
    function _diamondCut(
        FacetCut[] memory facetCuts,
        address target,
        bytes memory data
    ) internal virtual {
        DiamondBaseStorage.Layout storage l = DiamondBaseStorage.layout();

        unchecked {
            uint256 originalSelectorCount = l.selectorCount;
            uint256 selectorCount = originalSelectorCount;
            bytes32 selectorSlot;

            // Check if last selector slot is not full
            if (selectorCount & 7 > 0) {
                // get last selectorSlot
                selectorSlot = l.selectorSlots[selectorCount >> 3];
            }

            for (uint256 i; i < facetCuts.length; i++) {
                FacetCut memory facetCut = facetCuts[i];
                FacetCutAction action = facetCut.action;

                if (facetCut.selectors.length == 0)
                    revert DiamondWritable__SelectorNotSpecified();

                if (action == FacetCutAction.ADD) {
                    (selectorCount, selectorSlot) = _addFacetSelectors(
                        l,
                        selectorCount,
                        selectorSlot,
                        facetCut
                    );
                } else if (action == FacetCutAction.REPLACE) {
                    _replaceFacetSelectors(l, facetCut);
                } else if (action == FacetCutAction.REMOVE) {
                    (selectorCount, selectorSlot) = _removeFacetSelectors(
                        l,
                        selectorCount,
                        selectorSlot,
                        facetCut
                    );
                }
            }

            if (selectorCount != originalSelectorCount) {
                l.selectorCount = uint16(selectorCount);
            }

            // If last selector slot is not full
            if (selectorCount & 7 > 0) {
                l.selectorSlots[selectorCount >> 3] = selectorSlot;
            }

            emit DiamondCut(facetCuts, target, data);
            _initialize(target, data);
        }
    }

    function _addFacetSelectors(
        DiamondBaseStorage.Layout storage l,
        uint256 selectorCount,
        bytes32 selectorSlot,
        FacetCut memory facetCut
    ) internal returns (uint256, bytes32) {
        unchecked {
            if (
                facetCut.target != address(this) &&
                !facetCut.target.isContract()
            ) revert DiamondWritable__TargetHasNoCode();

            for (uint256 i; i < facetCut.selectors.length; i++) {
                bytes4 selector = facetCut.selectors[i];
                bytes32 oldFacet = l.facets[selector];

                if (address(bytes20(oldFacet)) != address(0))
                    revert DiamondWritable__SelectorAlreadyAdded();

                // add facet for selector
                l.facets[selector] =
                    bytes20(facetCut.target) |
                    bytes32(selectorCount);
                uint256 selectorInSlotPosition = (selectorCount & 7) << 5;

                // clear selector position in slot and add selector
                selectorSlot =
                    (selectorSlot &
                        ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) |
                    (bytes32(selector) >> selectorInSlotPosition);

                // if slot is full then write it to storage
                if (selectorInSlotPosition == 224) {
                    l.selectorSlots[selectorCount >> 3] = selectorSlot;
                    selectorSlot = 0;
                }

                selectorCount++;
            }

            return (selectorCount, selectorSlot);
        }
    }

    function _removeFacetSelectors(
        DiamondBaseStorage.Layout storage l,
        uint256 selectorCount,
        bytes32 selectorSlot,
        FacetCut memory facetCut
    ) internal returns (uint256, bytes32) {
        unchecked {
            if (facetCut.target != address(0))
                revert DiamondWritable__RemoveTargetNotZeroAddress();

            uint256 selectorSlotCount = selectorCount >> 3;
            uint256 selectorInSlotIndex = selectorCount & 7;

            for (uint256 i; i < facetCut.selectors.length; i++) {
                bytes4 selector = facetCut.selectors[i];
                bytes32 oldFacet = l.facets[selector];

                if (address(bytes20(oldFacet)) == address(0))
                    revert DiamondWritable__SelectorNotFound();

                if (address(bytes20(oldFacet)) == address(this))
                    revert DiamondWritable__SelectorIsImmutable();

                if (selectorSlot == 0) {
                    selectorSlotCount--;
                    selectorSlot = l.selectorSlots[selectorSlotCount];
                    selectorInSlotIndex = 7;
                } else {
                    selectorInSlotIndex--;
                }

                bytes4 lastSelector;
                uint256 oldSelectorsSlotCount;
                uint256 oldSelectorInSlotPosition;

                // adding a block here prevents stack too deep error
                {
                    // replace selector with last selector in l.facets
                    lastSelector = bytes4(
                        selectorSlot << (selectorInSlotIndex << 5)
                    );

                    if (lastSelector != selector) {
                        // update last selector slot position info
                        l.facets[lastSelector] =
                            (oldFacet & CLEAR_ADDRESS_MASK) |
                            bytes20(l.facets[lastSelector]);
                    }

                    delete l.facets[selector];
                    uint256 oldSelectorCount = uint16(uint256(oldFacet));
                    oldSelectorsSlotCount = oldSelectorCount >> 3;
                    oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;
                }

                if (oldSelectorsSlotCount != selectorSlotCount) {
                    bytes32 oldSelectorSlot = l.selectorSlots[
                        oldSelectorsSlotCount
                    ];

                    // clears the selector we are deleting and puts the last selector in its place.
                    oldSelectorSlot =
                        (oldSelectorSlot &
                            ~(CLEAR_SELECTOR_MASK >>
                                oldSelectorInSlotPosition)) |
                        (bytes32(lastSelector) >> oldSelectorInSlotPosition);

                    // update storage with the modified slot
                    l.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;
                } else {
                    // clears the selector we are deleting and puts the last selector in its place.
                    selectorSlot =
                        (selectorSlot &
                            ~(CLEAR_SELECTOR_MASK >>
                                oldSelectorInSlotPosition)) |
                        (bytes32(lastSelector) >> oldSelectorInSlotPosition);
                }

                if (selectorInSlotIndex == 0) {
                    delete l.selectorSlots[selectorSlotCount];
                    selectorSlot = 0;
                }
            }

            selectorCount = (selectorSlotCount << 3) | selectorInSlotIndex;

            return (selectorCount, selectorSlot);
        }
    }

    function _replaceFacetSelectors(
        DiamondBaseStorage.Layout storage l,
        FacetCut memory facetCut
    ) internal {
        unchecked {
            if (!facetCut.target.isContract())
                revert DiamondWritable__TargetHasNoCode();

            for (uint256 i; i < facetCut.selectors.length; i++) {
                bytes4 selector = facetCut.selectors[i];
                bytes32 oldFacet = l.facets[selector];
                address oldFacetAddress = address(bytes20(oldFacet));

                if (oldFacetAddress == address(0))
                    revert DiamondWritable__SelectorNotFound();
                if (oldFacetAddress == address(this))
                    revert DiamondWritable__SelectorIsImmutable();
                if (oldFacetAddress == facetCut.target)
                    revert DiamondWritable__ReplaceTargetIsIdentical();

                // replace old facet address
                l.facets[selector] =
                    (oldFacet & CLEAR_ADDRESS_MASK) |
                    bytes20(facetCut.target);
            }
        }
    }

    function _initialize(address target, bytes memory data) private {
        if ((target == address(0)) != (data.length == 0))
            revert DiamondWritable__InvalidInitializationParameters();

        if (target != address(0)) {
            if (target != address(this)) {
                if (!target.isContract())
                    revert DiamondWritable__TargetHasNoCode();
            }

            (bool success, ) = target.delegatecall(data);

            if (!success) {
                assembly {
                    returndatacopy(0, 0, returndatasize())
                    revert(0, returndatasize())
                }
            }
        }
    }
}

File 32 of 49 : IDiamondWritable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IDiamondWritableInternal } from './IDiamondWritableInternal.sol';

/**
 * @title Diamond proxy upgrade interface
 * @dev see https://eips.ethereum.org/EIPS/eip-2535
 */
interface IDiamondWritable is IDiamondWritableInternal {
    /**
     * @notice update diamond facets and optionally execute arbitrary initialization function
     * @param facetCuts array of structured Diamond facet update data
     * @param target optional target of initialization delegatecall
     * @param data optional initialization function call data
     */
    function diamondCut(
        FacetCut[] calldata facetCuts,
        address target,
        bytes calldata data
    ) external;
}

File 33 of 49 : IDiamondWritableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

interface IDiamondWritableInternal {
    enum FacetCutAction {
        ADD,
        REPLACE,
        REMOVE
    }

    event DiamondCut(FacetCut[] facetCuts, address target, bytes data);

    error DiamondWritable__InvalidInitializationParameters();
    error DiamondWritable__RemoveTargetNotZeroAddress();
    error DiamondWritable__ReplaceTargetIsIdentical();
    error DiamondWritable__SelectorAlreadyAdded();
    error DiamondWritable__SelectorIsImmutable();
    error DiamondWritable__SelectorNotFound();
    error DiamondWritable__SelectorNotSpecified();
    error DiamondWritable__TargetHasNoCode();

    struct FacetCut {
        address target;
        FacetCutAction action;
        bytes4[] selectors;
    }
}

File 34 of 49 : IProxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

interface IProxy {
    error Proxy__ImplementationIsNotContract();

    fallback() external payable;
}

File 35 of 49 : Proxy.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { AddressUtils } from '../utils/AddressUtils.sol';
import { IProxy } from './IProxy.sol';

/**
 * @title Base proxy contract
 */
abstract contract Proxy is IProxy {
    using AddressUtils for address;

    /**
     * @notice delegate all calls to implementation contract
     * @dev reverts if implementation address contains no code, for compatibility with metamorphic contracts
     * @dev memory location in use by assembly may be unsafe in other contexts
     */
    fallback() external payable virtual {
        address implementation = _getImplementation();

        if (!implementation.isContract())
            revert Proxy__ImplementationIsNotContract();

        assembly {
            calldatacopy(0, 0, calldatasize())
            let result := delegatecall(
                gas(),
                implementation,
                0,
                calldatasize(),
                0,
                0
            )
            returndatacopy(0, 0, returndatasize())

            switch result
            case 0 {
                revert(0, returndatasize())
            }
            default {
                return(0, returndatasize())
            }
        }
    }

    /**
     * @notice get logic implementation address
     * @return implementation address
     */
    function _getImplementation() internal virtual returns (address);
}

File 36 of 49 : IPausable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IPausableInternal } from './IPausableInternal.sol';

interface IPausable is IPausableInternal {
    /**
     * @notice query whether contract is paused
     * @return status whether contract is paused
     */
    function paused() external view returns (bool status);
}

File 37 of 49 : IPausableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

interface IPausableInternal {
    error Pausable__Paused();
    error Pausable__NotPaused();

    event Paused(address account);
    event Unpaused(address account);
}

File 38 of 49 : Pausable.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IPausable } from './IPausable.sol';
import { PausableInternal } from './PausableInternal.sol';

/**
 * @title Pausable security control module.
 */
abstract contract Pausable is IPausable, PausableInternal {
    /**
     * @inheritdoc IPausable
     */
    function paused() external view virtual returns (bool status) {
        status = _paused();
    }
}

File 39 of 49 : PausableInternal.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IPausableInternal } from './IPausableInternal.sol';
import { PausableStorage } from './PausableStorage.sol';

/**
 * @title Internal functions for Pausable security control module.
 */
abstract contract PausableInternal is IPausableInternal {
    modifier whenNotPaused() {
        if (_paused()) revert Pausable__Paused();
        _;
    }

    modifier whenPaused() {
        if (!_paused()) revert Pausable__NotPaused();
        _;
    }

    /**
     * @notice query whether contract is paused
     * @return status whether contract is paused
     */
    function _paused() internal view virtual returns (bool status) {
        status = PausableStorage.layout().paused;
    }

    /**
     * @notice Triggers paused state, when contract is unpaused.
     */
    function _pause() internal virtual whenNotPaused {
        PausableStorage.layout().paused = true;
        emit Paused(msg.sender);
    }

    /**
     * @notice Triggers unpaused state, when contract is paused.
     */
    function _unpause() internal virtual whenPaused {
        delete PausableStorage.layout().paused;
        emit Unpaused(msg.sender);
    }
}

File 40 of 49 : PausableStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

library PausableStorage {
    struct Layout {
        bool paused;
    }

    bytes32 internal constant STORAGE_SLOT =
        keccak256('solidstate.contracts.storage.Pausable');

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

File 41 of 49 : IReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IReentrancyGuard {
    error ReentrancyGuard__ReentrantCall();
}

File 42 of 49 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { IReentrancyGuard } from './IReentrancyGuard.sol';
import { ReentrancyGuardStorage } from './ReentrancyGuardStorage.sol';

/**
 * @title Utility contract for preventing reentrancy attacks
 */
abstract contract ReentrancyGuard is IReentrancyGuard {
    uint256 internal constant REENTRANCY_STATUS_LOCKED = 2;
    uint256 internal constant REENTRANCY_STATUS_UNLOCKED = 1;

    modifier nonReentrant() virtual {
        if (_isReentrancyGuardLocked()) revert ReentrancyGuard__ReentrantCall();
        _lockReentrancyGuard();
        _;
        _unlockReentrancyGuard();
    }

    /**
     * @notice returns true if the reentrancy guard is locked, false otherwise
     */
    function _isReentrancyGuardLocked() internal view virtual returns (bool) {
        return
            ReentrancyGuardStorage.layout().status == REENTRANCY_STATUS_LOCKED;
    }

    /**
     * @notice lock functions that use the nonReentrant modifier
     */
    function _lockReentrancyGuard() internal virtual {
        ReentrancyGuardStorage.layout().status = REENTRANCY_STATUS_LOCKED;
    }

    /**
     * @notice unlock functions that use the nonReentrant modifier
     */
    function _unlockReentrancyGuard() internal virtual {
        ReentrancyGuardStorage.layout().status = REENTRANCY_STATUS_UNLOCKED;
    }
}

File 43 of 49 : ReentrancyGuardStorage.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

library ReentrancyGuardStorage {
    struct Layout {
        uint256 status;
    }

    bytes32 internal constant STORAGE_SLOT =
        keccak256('solidstate.contracts.storage.ReentrancyGuard');

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

File 44 of 49 : AddressUtils.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

import { UintUtils } from './UintUtils.sol';

library AddressUtils {
    using UintUtils for uint256;

    error AddressUtils__InsufficientBalance();
    error AddressUtils__NotContract();
    error AddressUtils__SendValueFailed();

    function toString(address account) internal pure returns (string memory) {
        return uint256(uint160(account)).toHexString(20);
    }

    function isContract(address account) internal view returns (bool) {
        uint256 size;
        assembly {
            size := extcodesize(account)
        }
        return size > 0;
    }

    function sendValue(address payable account, uint256 amount) internal {
        (bool success, ) = account.call{ value: amount }('');
        if (!success) revert AddressUtils__SendValueFailed();
    }

    function functionCall(
        address target,
        bytes memory data
    ) internal returns (bytes memory) {
        return
            functionCall(target, data, 'AddressUtils: failed low-level call');
    }

    function functionCall(
        address target,
        bytes memory data,
        string memory error
    ) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, error);
    }

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return
            functionCallWithValue(
                target,
                data,
                value,
                'AddressUtils: failed low-level call with value'
            );
    }

    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory error
    ) internal returns (bytes memory) {
        if (value > address(this).balance)
            revert AddressUtils__InsufficientBalance();
        return _functionCallWithValue(target, data, value, error);
    }

    /**
     * @notice execute arbitrary external call with limited gas usage and amount of copied return data
     * @dev derived from https://github.com/nomad-xyz/ExcessivelySafeCall (MIT License)
     * @param target recipient of call
     * @param gasAmount gas allowance for call
     * @param value native token value to include in call
     * @param maxCopy maximum number of bytes to copy from return data
     * @param data encoded call data
     * @return success whether call is successful
     * @return returnData copied return data
     */
    function excessivelySafeCall(
        address target,
        uint256 gasAmount,
        uint256 value,
        uint16 maxCopy,
        bytes memory data
    ) internal returns (bool success, bytes memory returnData) {
        returnData = new bytes(maxCopy);

        assembly {
            // execute external call via assembly to avoid automatic copying of return data
            success := call(
                gasAmount,
                target,
                value,
                add(data, 0x20),
                mload(data),
                0,
                0
            )

            // determine whether to limit amount of data to copy
            let toCopy := returndatasize()

            if gt(toCopy, maxCopy) {
                toCopy := maxCopy
            }

            // store the length of the copied bytes
            mstore(returnData, toCopy)

            // copy the bytes from returndata[0:toCopy]
            returndatacopy(add(returnData, 0x20), 0, toCopy)
        }
    }

    function _functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory error
    ) private returns (bytes memory) {
        if (!isContract(target)) revert AddressUtils__NotContract();

        (bool success, bytes memory returnData) = target.call{ value: value }(
            data
        );

        if (success) {
            return returnData;
        } else if (returnData.length > 0) {
            assembly {
                let returnData_size := mload(returnData)
                revert(add(32, returnData), returnData_size)
            }
        } else {
            revert(error);
        }
    }
}

File 45 of 49 : UintUtils.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.8;

/**
 * @title utility functions for uint256 operations
 * @dev derived from https://github.com/OpenZeppelin/openzeppelin-contracts/ (MIT license)
 */
library UintUtils {
    error UintUtils__InsufficientHexLength();

    bytes16 private constant HEX_SYMBOLS = '0123456789abcdef';

    function add(uint256 a, int256 b) internal pure returns (uint256) {
        return b < 0 ? sub(a, -b) : a + uint256(b);
    }

    function sub(uint256 a, int256 b) internal pure returns (uint256) {
        return b < 0 ? add(a, -b) : a - uint256(b);
    }

    function toString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return '0';
        }

        uint256 temp = value;
        uint256 digits;

        while (temp != 0) {
            digits++;
            temp /= 10;
        }

        bytes memory buffer = new bytes(digits);

        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }

        return string(buffer);
    }

    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return '0x00';
        }

        uint256 length = 0;

        for (uint256 temp = value; temp != 0; temp >>= 8) {
            unchecked {
                length++;
            }
        }

        return toHexString(value, length);
    }

    function toHexString(
        uint256 value,
        uint256 length
    ) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = '0';
        buffer[1] = 'x';

        unchecked {
            for (uint256 i = 2 * length + 1; i > 1; --i) {
                buffer[i] = HEX_SYMBOLS[value & 0xf];
                value >>= 4;
            }
        }

        if (value != 0) revert UintUtils__InsufficientHexLength();

        return string(buffer);
    }
}

File 46 of 49 : Constants.sol
// SPDX-License-Identifier: AGPL-3.0-only

pragma solidity 0.8.19;

/**
 * @dev The default token decimals value
 */
uint256 constant DECIMALS_DEFAULT = 18;

/**
 * @dev The maximum uint256 value for swap amount limit settings
 */
uint256 constant INFINITY = type(uint256).max;

/**
 * @dev The default limit of account list size
 */
uint256 constant LIST_SIZE_LIMIT_DEFAULT = 100;

/**
 * @dev The limit of swap router list size
 */
uint256 constant LIST_SIZE_LIMIT_ROUTERS = 200;

/**
 * @dev The factor for percentage settings. Example: 100 is 0.1%
 */
uint256 constant MILLIPERCENT_FACTOR = 100_000;

/**
 * @dev The de facto standard address to denote the native token
 */
address constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

File 47 of 49 : TransferHelper.sol
// SPDX-License-Identifier: AGPL-3.0-only

pragma solidity 0.8.19;

/**
 * @notice Emitted when an approval action fails
 */
error SafeApproveError();

/**
 * @notice Emitted when a transfer action fails
 */
error SafeTransferError();

/**
 * @notice Emitted when a transferFrom action fails
 */
error SafeTransferFromError();

/**
 * @notice Emitted when a transfer of the native token fails
 */
error SafeTransferNativeError();

/**
 * @notice Safely approve the token to the account
 * @param _token The token address
 * @param _to The token approval recipient address
 * @param _value The token approval amount
 */
function safeApprove(address _token, address _to, uint256 _value) {
    // 0x095ea7b3 is the selector for "approve(address,uint256)"
    (bool success, bytes memory data) = _token.call(
        abi.encodeWithSelector(0x095ea7b3, _to, _value)
    );

    bool condition = success && (data.length == 0 || abi.decode(data, (bool)));

    if (!condition) {
        revert SafeApproveError();
    }
}

/**
 * @notice Safely transfer the token to the account
 * @param _token The token address
 * @param _to The token transfer recipient address
 * @param _value The token transfer amount
 */
function safeTransfer(address _token, address _to, uint256 _value) {
    // 0xa9059cbb is the selector for "transfer(address,uint256)"
    (bool success, bytes memory data) = _token.call(
        abi.encodeWithSelector(0xa9059cbb, _to, _value)
    );

    bool condition = success && (data.length == 0 || abi.decode(data, (bool)));

    if (!condition) {
        revert SafeTransferError();
    }
}

/**
 * @notice Safely transfer the token between the accounts
 * @param _token The token address
 * @param _from The token transfer source address
 * @param _to The token transfer recipient address
 * @param _value The token transfer amount
 */
function safeTransferFrom(address _token, address _from, address _to, uint256 _value) {
    // 0x23b872dd is the selector for "transferFrom(address,address,uint256)"
    (bool success, bytes memory data) = _token.call(
        abi.encodeWithSelector(0x23b872dd, _from, _to, _value)
    );

    bool condition = success && (data.length == 0 || abi.decode(data, (bool)));

    if (!condition) {
        revert SafeTransferFromError();
    }
}

/**
 * @notice Safely transfer the native token to the account
 * @param _to The native token transfer recipient address
 * @param _value The native token transfer amount
 */
function safeTransferNative(address _to, uint256 _value) {
    (bool success, ) = _to.call{ value: _value }(new bytes(0));

    if (!success) {
        revert SafeTransferNativeError();
    }
}

File 48 of 49 : ITokenBalance.sol
// SPDX-License-Identifier: AGPL-3.0-only

pragma solidity 0.8.19;

/**
 * @title ITokenBalance
 * @notice Token balance interface
 */
interface ITokenBalance {
    /**
     * @notice Getter of the token balance by the account
     * @param _account The account address
     * @return Token balance
     */
    function balanceOf(address _account) external view returns (uint256);
}

File 49 of 49 : OFTWrapperStorage.sol
// SPDX-License-Identifier: AGPL-3.0-only

pragma solidity 0.8.19;

/**
 * @title OFTWrapperStorage
 * @notice OFTWrapperDiamond storage
 */
library OFTWrapperStorage {
    /**
     * @notice OFTWrapperDiamond storage layout
     * @param collector The address of the collector
     */
    struct Layout {
        address collector;
    }

    bytes32 internal constant STORAGE_SLOT = keccak256('interport.oft.wrapper.OFTWrapperDiamond');

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

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_collector","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"DiamondWritable__InvalidInitializationParameters","type":"error"},{"inputs":[],"name":"DiamondWritable__RemoveTargetNotZeroAddress","type":"error"},{"inputs":[],"name":"DiamondWritable__ReplaceTargetIsIdentical","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorAlreadyAdded","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorIsImmutable","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorNotFound","type":"error"},{"inputs":[],"name":"DiamondWritable__SelectorNotSpecified","type":"error"},{"inputs":[],"name":"DiamondWritable__TargetHasNoCode","type":"error"},{"inputs":[],"name":"ERC165Base__InvalidInterfaceId","type":"error"},{"inputs":[],"name":"Ownable__NotOwner","type":"error"},{"inputs":[],"name":"Ownable__NotTransitiveOwner","type":"error"},{"inputs":[],"name":"Pausable__NotPaused","type":"error"},{"inputs":[],"name":"Pausable__Paused","type":"error"},{"inputs":[],"name":"Proxy__ImplementationIsNotContract","type":"error"},{"inputs":[],"name":"ReentrancyGuard__ReentrantCall","type":"error"},{"inputs":[],"name":"SafeOwnable__NotNomineeOwner","type":"error"},{"inputs":[],"name":"SafeTransferError","type":"error"},{"inputs":[],"name":"SafeTransferNativeError","type":"error"},{"anonymous":false,"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"enum IDiamondWritableInternal.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"indexed":false,"internalType":"struct IDiamondWritableInternal.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"DiamondCut","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"collector","type":"address"}],"name":"SetCollector","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[],"name":"SYSTEM_VERSION_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"cleanup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"}],"name":"cleanupWithAmount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"collector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"enum IDiamondWritableInternal.FacetCutAction","name":"action","type":"uint8"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct IDiamondWritableInternal.FacetCut[]","name":"facetCuts","type":"tuple[]"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"diamondCut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"facetAddress","outputs":[{"internalType":"address","name":"facet","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facetAddresses","outputs":[{"internalType":"address[]","name":"addresses","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"facet","type":"address"}],"name":"facetFunctionSelectors","outputs":[{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"facets","outputs":[{"components":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4[]","name":"selectors","type":"bytes4[]"}],"internalType":"struct IDiamondReadable.Facet[]","name":"diamondFacets","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"forceTransferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getFallbackAddress","outputs":[{"internalType":"address","name":"fallbackAddress","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nomineeOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"status","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collector","type":"address"}],"name":"setCollector","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"fallbackAddress","type":"address"}],"name":"setFallbackAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddress","type":"address"}],"name":"tokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040523480156200001157600080fd5b50604051620038383803806200383883398101604081905262000034916200119a565b60408051600c8082526101a0820190925260009160208201610180803683370190505090506000632c40805960e01b82826200007081620011d2565b935081518110620000855762000085620011fa565b6001600160e01b031990921660209283029190910190910152639142376560e01b8282620000b381620011d2565b935081518110620000c857620000c8620011fa565b6001600160e01b031990921660209283029190910190910152620000f5632f40adcf60e21b6001620004ed565b6307e4c70760e21b82826200010a81620011d2565b9350815181106200011f576200011f620011fa565b6001600160e01b0319909216602092830291909101909101526200014c6307e4c70760e21b6001620004ed565b637a0ed62760e01b82826200016181620011d2565b935081518110620001765762000176620011fa565b6001600160e01b0319909216602092830291909101909101526356fe50af60e11b8282620001a481620011d2565b935081518110620001b957620001b9620011fa565b6001600160e01b0319909216602092830291909101909101526314bbdacb60e21b8282620001e781620011d2565b935081518110620001fc57620001fc620011fa565b6001600160e01b0319909216602092830291909101909101526366ffd66360e11b82826200022a81620011d2565b9350815181106200023f576200023f620011fa565b6001600160e01b0319909216602092830291909101909101526200026c6348e2b09360e01b6001620004ed565b6301ffc9a760e01b82826200028181620011d2565b935081518110620002965762000296620011fa565b6001600160e01b031990921660209283029190910190910152620002c36301ffc9a760e01b6001620004ed565b638da5cb5b60e01b8282620002d881620011d2565b935081518110620002ed57620002ed620011fa565b6001600160e01b03199092166020928302919091019091015263455a8a8560e11b82826200031b81620011d2565b935081518110620003305762000330620011fa565b6001600160e01b03199092166020928302919091019091015263f2fde38b60e01b82826200035e81620011d2565b935081518110620003735762000373620011fa565b6001600160e01b0319909216602092830291909101909101526379ba509760e01b8282620003a181620011d2565b935081518110620003b657620003b6620011fa565b6001600160e01b031990921660209283029190910190910152620003e36307f5828d60e41b6001620004ed565b604080516001808252818301909252600091816020015b60408051606080820183526000808352602083015291810191909152815260200190600190039081620003fa57905050604080516060810190915230815290915060208101600081526020018481525081600081518110620004605762000460620011fa565b60200260200101819052506200048e816000604051806020016040528060008152506200056460201b60201c565b620004993362000765565b50620004a7915050620007df565b620004b28262000b69565b6001600160a01b0381163314801590620004d457506001600160a01b03811615155b15620004e557620004e58162000765565b50506200139f565b6001600160e01b03198083169003620005195760405163b0a19dd560e01b815260040160405180910390fd5b6001600160e01b03199190911660009081527ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d860205260409020805460ff1916911515919091179055565b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94547f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc939061ffff811690819060009060071615620005d45750600381901c60009081526002840160205260409020545b60005b8751811015620006d3576000888281518110620005f857620005f8620011fa565b60200260200101519050600081602001519050816040015151600003620006325760405163eb6c3aeb60e01b815260040160405180910390fd5b600081600281111562000649576200064962001210565b0362000668576200065d8786868562000bd2565b9095509350620006c8565b60018160028111156200067f576200067f62001210565b03620006975762000691878362000d1a565b620006c8565b6002816002811115620006ae57620006ae62001210565b03620006c857620006c28786868562000e64565b90955093505b5050600101620005d7565b50828214620006f05760018401805461ffff191661ffff84161790555b60078216156200071357600382901c600090815260028501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67387878760405162000748939291906200127a565b60405180910390a16200075c868662001090565b50505050505050565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046080546040516001600160a01b038481169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a380546001600160a01b0319166001600160a01b0392909216919091179055565b60408051600a808252610160820190925260009160208201610140803683370190505090506000635c975abb60e01b82826200081b81620011d2565b935081518110620008305762000830620011fa565b6001600160e01b0319909216602092830291909101909101526200085d635c975abb60e01b6001620004ed565b630fb5b82d60e41b82826200087281620011d2565b935081518110620008875762000887620011fa565b6001600160e01b03199092166020928302919091019091015263913e77ad60e01b8282620008b581620011d2565b935081518110620008ca57620008ca620011fa565b6001600160e01b031990921660209283029190910190910152638456cb5960e01b8282620008f881620011d2565b9350815181106200090d576200090d620011fa565b6001600160e01b031990921660209283029190910190910152631fa5d41d60e11b82826200093b81620011d2565b935081518110620009505762000950620011fa565b6001600160e01b031990921660209283029190910190910152631513622560e31b82826200097e81620011d2565b935081518110620009935762000993620011fa565b6001600160e01b031990921660209283029190910190910152637dd677e760e11b8282620009c181620011d2565b935081518110620009d657620009d6620011fa565b6001600160e01b03199092166020928302919091019091015263160b7c9360e11b828262000a0481620011d2565b93508151811062000a195762000a19620011fa565b6001600160e01b03199092166020928302919091019091015263776e4b3560e11b828262000a4781620011d2565b93508151811062000a5c5762000a5c620011fa565b6001600160e01b03199092166020928302919091019091015263093f0e2760e01b828262000a8a81620011d2565b93508151811062000a9f5762000a9f620011fa565b6001600160e01b03199290921660209283029190910190910152604080516001808252818301909252600091816020015b6040805160608082018352600080835260208301529181019190915281526020019060019003908162000ad05790505060408051606081019091523081529091506020810160008152602001848152508160008151811062000b365762000b36620011fa565b602002602001018190525062000b64816000604051806020016040528060008152506200056460201b60201c565b505050565b7f8135b9b8d3411dab68efe82c12999875113f270399aa3b0126860dde293ca8f380546001600160a01b0319166001600160a01b0383169081179091556040517f0cc5437d7c9c1d9eab549acbb533eea3e9868e9443dd75309ed5820b33a3774e90600090a250565b805160009081906001600160a01b0316301480159062000bfb575082516001600160a01b03163b155b1562000c1a57604051633ddc5cab60e21b815260040160405180910390fd5b60005b83604001515181101562000d0d5760008460400151828151811062000c465762000c46620011fa565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c1562000c9357604051634923a77160e11b815260040160405180910390fd5b85516001600160e01b0319838116600081815260208d90526040902060609390931b6001600160601b0319168b1790925560058a901b60e090811692831c91831c1999909916179781900362000cfd57600389901c600090815260028b0160205260408120989098555b5050506001958601950162000c1d565b5093959294509192505050565b80516001600160a01b03163b62000d4457604051633ddc5cab60e21b815260040160405180910390fd5b60005b81604001515181101562000b645760008260400151828151811062000d705762000d70620011fa565b6020908102919091018101516001600160e01b03198116600090815291869052604090912054909150606081901c8062000dbd576040516337e25a9760e11b815260040160405180910390fd5b306001600160a01b0382160362000de75760405163e983573160e01b815260040160405180910390fd5b84600001516001600160a01b0316816001600160a01b03160362000e1e576040516330baabf360e11b815260040160405180910390fd5b5083516001600160e01b031992909216600090815260208690526040902060609290921b6001600160601b0319166001600160601b039190911617905560010162000d47565b805160009081906001600160a01b03161562000e9357604051633ab3490960e21b815260040160405180910390fd5b600385901c6007861660005b8560400151518110156200107c5760008660400151828151811062000ec85762000ec8620011fa565b6020908102919091018101516001600160e01b031981166000908152918c9052604090912054909150606081901c62000f14576040516337e25a9760e11b815260040160405180910390fd5b30606082901c0362000f395760405163e983573160e01b815260040160405180910390fd5b600089900362000f6757600019909401600081815260028c0160205260409020549850936007935062000f6f565b600019909301925b600584901b89901b6000806001600160e01b03198084169086161462000fc2576001600160e01b03198316600090815260208f90526040902080546001600160601b0319166001600160601b0386161790555b50506001600160e01b03198316600090815260208d90526040812055611fff600383901c1660e0600584901b168782146200102757600082815260028f016020526040902080546001600160e01b031980841c19909116908516831c1790556200104b565b80836001600160e01b031916901c816001600160e01b031960001b901c198d16179b505b866000036200106a57600088815260028f01602052604081208190559b505b50506001909301925062000e9f915050565b5060039190911b1796939550929350505050565b8051156001600160a01b0383161514620010bd576040516326df4ccd60e01b815260040160405180910390fd5b6001600160a01b0382161562001179576001600160a01b038216301462001107576001600160a01b0382163b6200110757604051633ddc5cab60e21b815260040160405180910390fd5b6000826001600160a01b03168260405162001123919062001381565b600060405180830381855af49150503d806000811462001160576040519150601f19603f3d011682016040523d82523d6000602084013e62001165565b606091505b505090508062000b64573d6000803e3d6000fd5b5050565b80516001600160a01b03811681146200119557600080fd5b919050565b60008060408385031215620011ae57600080fd5b620011b9836200117d565b9150620011c9602084016200117d565b90509250929050565b600060018201620011f357634e487b7160e01b600052601160045260246000fd5b5060010190565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b60005b838110156200124357818101518382015260200162001229565b50506000910152565b600081518084526200126681602086016020860162001226565b601f01601f19169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b848110156200134f57898403607f19018652815180516001600160a01b03168552838101518986019060038110620012eb57634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015620013395783516001600160e01b03191682529286019260019290920191908601906200130d565b50978501979550505090820190600101620012a3565b50506001600160a01b038a169088015286810360408801526200137381896200124c565b9a9950505050505050505050565b600082516200139581846020870162001226565b9190910192915050565b61248980620013af6000396000f3fe6080604052600436106101395760003560e01c80638ab5150a116100ab578063adfca15e1161006f578063adfca15e14610390578063cdffacc6146103bd578063eedc966a14610404578063f2fde38b14610424578063fb5b82d014610444578063fbacefce1461046457610140565b80638ab5150a146103115780638da5cb5b14610326578063913e77ad1461033b5780639142376514610350578063a89b11281461037057610140565b80633f4ba83a116100fd5780633f4ba83a1461027957806352ef6b2c1461028e5780635c975abb146102b057806379ba5097146102c55780637a0ed627146102da5780638456cb59146102fc57610140565b806301ffc9a71461019a578063093f0e27146101cf5780631f931c1c1461020c5780632c16f9261461022c5780632c4080591461024c57610140565b3661014057005b600061014a610484565b90506001600160a01b0381163b610174576040516321f27f0d60e21b815260040160405180910390fd5b3660008037600080366000845af43d6000803e808015610193573d6000f35b3d6000fd5b005b3480156101a657600080fd5b506101ba6101b5366004611d77565b610493565b60405190151581526020015b60405180910390f35b3480156101db57600080fd5b507f22ad9585a395edc8067b50da4778cafbb7fa2c4bbd7619fad6aeba403857fd745b6040519081526020016101c6565b34801561021857600080fd5b50610198610227366004611df9565b6104d6565b34801561023857600080fd5b50610198610247366004611eab565b610560565b34801561025857600080fd5b506102616105d7565b6040516001600160a01b0390911681526020016101c6565b34801561028557600080fd5b5061019861060a565b34801561029a57600080fd5b506102a361067d565b6040516101c69190611ed5565b3480156102bc57600080fd5b506101ba61082f565b3480156102d157600080fd5b5061019861084a565b3480156102e657600080fd5b506102ef61088b565b6040516101c69190611f67565b34801561030857600080fd5b50610198610cc2565b34801561031d57600080fd5b50610261610d34565b34801561033257600080fd5b50610261610d3e565b34801561034757600080fd5b50610261610d48565b34801561035c57600080fd5b5061019861036b366004611fe4565b610d7b565b34801561037c57600080fd5b5061019861038b366004611fe4565b610df4565b34801561039c57600080fd5b506103b06103ab366004611fe4565b610e36565b6040516101c69190611fff565b3480156103c957600080fd5b506102616103d8366004611d77565b6001600160e01b0319166000908152600080516020612434833981519152602052604090205460601c90565b34801561041057600080fd5b506101fe61041f366004611fe4565b610f91565b34801561043057600080fd5b5061019861043f366004611fe4565b61102c565b34801561045057600080fd5b5061019861045f366004611fe4565b61106e565b34801561047057600080fd5b5061019861047f366004611fe4565b6110b0565b600061048e61118d565b905090565b6001600160e01b0319811660009081527ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d8602052604081205460ff165b92915050565b6104de6111ee565b6001600160a01b0316336001600160a01b03161461050f57604051632f7a8ee160e01b815260040160405180910390fd5b61055961051c85876120d5565b8484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061121692505050565b5050505050565b6105686111ee565b6001600160a01b0316336001600160a01b03161461059957604051632f7a8ee160e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038316016105cc576105c833826113d2565b5050565b6105c8823383611465565b600061048e7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b6106126111ee565b6001600160a01b0316336001600160a01b03161461064357604051632f7a8ee160e01b815260040160405180910390fd5b6000805160206123f48339815191525460ff1661067357604051632ca4452d60e11b815260040160405180910390fd5b61067b611557565b565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff8111156106bc576106bc612041565b6040519080825280602002602001820160405280156106e5578160200160208202803683370190505b50915060008060005b600184015461ffff16821015610827576000818152600285016020526040812054905b600881101561081257836107248161221f565b600188015490955061ffff168511905061081257600581901b82901b6001600160e01b0319811660009081526020889052604081205460601c90805b888110156107b5578a818151811061077a5761077a612238565b60200260200101516001600160a01b0316836001600160a01b0316036107a357600191506107b5565b806107ad8161221f565b915050610760565b5080156107c457505050610800565b818a89815181106107d7576107d7612238565b6001600160a01b0390921660209283029190910190910152876107f98161221f565b9850505050505b8061080a8161221f565b915050610711565b5050808061081f9061221f565b9150506106ee565b505082525090565b600061048e6000805160206123f48339815191525460ff1690565b6108526115d4565b6001600160a01b0316336001600160a01b0316146108835760405163efd1052d60e01b815260040160405180910390fd5b61067b6115fc565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff8111156108ca576108ca612041565b60405190808252806020026020018201604052801561091057816020015b6040805180820190915260008152606060208201528152602001906001900390816108e85790505b50600182015490925060009061ffff1667ffffffffffffffff81111561093857610938612041565b604051908082528060200260200182016040528015610961578160200160208202803683370190505b50905060008060005b600185015461ffff16821015610c50576000818152600286016020526040812054905b6008811015610c3b57836109a08161221f565b600189015490955061ffff1685119050610c3b57600581901b82901b6001600160e01b0319811660009081526020899052604081205460601c90805b88811015610af957826001600160a01b03168c8281518110610a0057610a00612238565b6020026020010151600001516001600160a01b031603610ae757838c8281518110610a2d57610a2d612238565b6020026020010151602001518b8381518110610a4b57610a4b612238565b602002602001015160ff1681518110610a6657610a66612238565b60200260200101906001600160e01b03191690816001600160e01b0319168152505060ff8a8281518110610a9c57610a9c612238565b602002602001015160ff1610610ab157600080fd5b898181518110610ac357610ac3612238565b602002602001018051809190610ad89061224e565b60ff1690525060019150610af9565b80610af18161221f565b9150506109dc565b508015610b0857505050610c29565b818b8981518110610b1b57610b1b612238565b60209081029190910101516001600160a01b03909116905260018a015461ffff1667ffffffffffffffff811115610b5457610b54612041565b604051908082528060200260200182016040528015610b7d578160200160208202803683370190505b508b8981518110610b9057610b90612238565b602002602001015160200181905250828b8981518110610bb257610bb2612238565b602002602001015160200151600081518110610bd057610bd0612238565b60200260200101906001600160e01b03191690816001600160e01b031916815250506001898981518110610c0657610c06612238565b60ff9092166020928302919091019091015287610c228161221f565b9850505050505b80610c338161221f565b91505061098d565b50508080610c489061221f565b91505061096a565b5060005b82811015610cb7576000848281518110610c7057610c70612238565b602002602001015160ff1690506000878381518110610c9157610c91612238565b602002602001015160200151905081815250508080610caf9061221f565b915050610c54565b508185525050505090565b610cca6111ee565b6001600160a01b0316336001600160a01b031614610cfb57604051632f7a8ee160e01b815260040160405180910390fd5b6000805160206123f48339815191525460ff1615610d2c576040516302ca8ced60e11b815260040160405180910390fd5b61067b611636565b600061048e6115d4565b600061048e6111ee565b60007f8135b9b8d3411dab68efe82c12999875113f270399aa3b0126860dde293ca8f35b546001600160a01b0316919050565b610d836111ee565b6001600160a01b0316336001600160a01b031614610db457604051632f7a8ee160e01b815260040160405180910390fd5b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9680546001600160a01b0319166001600160a01b03831617905550565b50565b610dfc6111ee565b6001600160a01b0316336001600160a01b031614610e2d57604051632f7a8ee160e01b815260040160405180910390fd5b610df1816116b1565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff811115610e7557610e75612041565b604051908082528060200260200182016040528015610e9e578160200160208202803683370190505b50915060008060005b600184015461ffff16821015610f87576000818152600285016020526040812054905b6008811015610f725783610edd8161221f565b600188015490955061ffff1685119050610f7257600581901b82901b6001600160e01b0319811660009081526020889052604090205460601c6001600160a01b038a1603610f5f5780888781518110610f3857610f38612238565b6001600160e01b03199092166020928302919091019091015285610f5b8161221f565b9650505b5080610f6a8161221f565b915050610eca565b50508080610f7f9061221f565b915050610ea7565b5050825250919050565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601610fbf575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611003573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d0919061226d565b919050565b6110346111ee565b6001600160a01b0316336001600160a01b03161461106557604051632f7a8ee160e01b815260040160405180910390fd5b610df18161172b565b6110766111ee565b6001600160a01b0316336001600160a01b0316146110a757604051632f7a8ee160e01b815260040160405180910390fd5b610df18161176e565b6110b86111ee565b6001600160a01b0316336001600160a01b0316146110e957604051632f7a8ee160e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0382160161111857610df133476113d2565b6040516370a0823160e01b8152306004820152610df190829033906001600160a01b038316906370a0823190602401602060405180830381865afa158015611164573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611188919061226d565b611465565b600080356001600160e01b0319168152600080516020612434833981519152602052604090205460601c806111eb57507f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b90565b60007f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f671680460610d6c565b600080516020612414833981519152546000805160206124348339815191529061ffff8116908190600090600716156112615750600381901c60009081526002840160205260409020545b60005b875181101561134657600088828151811061128157611281612238565b602002602001015190506000816020015190508160400151516000036112ba5760405163eb6c3aeb60e01b815260040160405180910390fd5b60008160028111156112ce576112ce612286565b036112e9576112df878686856117d7565b909550935061133c565b60018160028111156112fd576112fd612286565b036113115761130c8783611916565b61133c565b600281600281111561132557611325612286565b0361133c5761133687868685611a5c565b90955093505b5050600101611264565b508282146113625760018401805461ffff191661ffff84161790555b600782161561138457600382901c600090815260028501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738787876040516113b7939291906122ec565b60405180910390a16113c98686611c7f565b50505050505050565b604080516000808252602082019092526001600160a01b0384169083906040516113fc91906123b5565b60006040518083038185875af1925050503d8060008114611439576040519150601f19603f3d011682016040523d82523d6000602084013e61143e565b606091505b505090508061146057604051632e05b05360e21b815260040160405180910390fd5b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916114c191906123b5565b6000604051808303816000865af19150503d80600081146114fe576040519150601f19603f3d011682016040523d82523d6000602084013e611503565b606091505b5091509150600082801561152f57508151158061152f57508180602001905181019061152f91906123d1565b90508061154f57604051632fdb1b7f60e11b815260040160405180910390fd5b505050505050565b6000805160206123f48339815191525460ff1661158757604051632ca4452d60e11b815260040160405180910390fd5b6000805160206123f4833981519152805460ff191690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60007f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce6617890610d6c565b611605336116b1565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319169055565b6000805160206123f48339815191525460ff1615611667576040516302ca8ced60e11b815260040160405180910390fd5b6000805160206123f4833981519152805460ff191660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016115ca565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046080546040516001600160a01b038481169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a380546001600160a01b0319166001600160a01b0392909216919091179055565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319166001600160a01b038316179055610df181818181565b7f8135b9b8d3411dab68efe82c12999875113f270399aa3b0126860dde293ca8f380546001600160a01b0319166001600160a01b0383169081179091556040517f0cc5437d7c9c1d9eab549acbb533eea3e9868e9443dd75309ed5820b33a3774e90600090a250565b805160009081906001600160a01b031630148015906117ff575082516001600160a01b03163b155b1561181d57604051633ddc5cab60e21b815260040160405180910390fd5b60005b8360400151518110156119095760008460400151828151811061184557611845612238565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c1561189157604051634923a77160e11b815260040160405180910390fd5b85516001600160e01b0319838116600081815260208d90526040902060609390931b6001600160601b0319168b1790925560058a901b60e090811692831c91831c199990991617978190036118fa57600389901c600090815260028b0160205260408120989098555b50505060019586019501611820565b5093959294509192505050565b80516001600160a01b03163b61193f57604051633ddc5cab60e21b815260040160405180910390fd5b60005b8160400151518110156114605760008260400151828151811061196757611967612238565b6020908102919091018101516001600160e01b03198116600090815291869052604090912054909150606081901c806119b3576040516337e25a9760e11b815260040160405180910390fd5b306001600160a01b038216036119dc5760405163e983573160e01b815260040160405180910390fd5b84600001516001600160a01b0316816001600160a01b031603611a12576040516330baabf360e11b815260040160405180910390fd5b5083516001600160e01b031992909216600090815260208690526040902060609290921b6001600160601b0319166bffffffffffffffffffffffff91909116179055600101611942565b805160009081906001600160a01b031615611a8a57604051633ab3490960e21b815260040160405180910390fd5b600385901c6007861660005b856040015151811015611c6b57600086604001518281518110611abb57611abb612238565b6020908102919091018101516001600160e01b031981166000908152918c9052604090912054909150606081901c611b06576040516337e25a9760e11b815260040160405180910390fd5b30606082901c03611b2a5760405163e983573160e01b815260040160405180910390fd5b6000899003611b5657600019909401600081815260028c01602052604090205498509360079350611b5e565b600019909301925b600584901b89901b6000806001600160e01b031980841690861614611bb5576001600160e01b03198316600090815260208f90526040902080546001600160601b0319166bffffffffffffffffffffffff86161790555b50506001600160e01b03198316600090815260208d90526040812055611fff600383901c1660e0600584901b16878214611c1857600082815260028f016020526040902080546001600160e01b031980841c19909116908516831c179055611c3c565b80836001600160e01b031916901c816001600160e01b031960001b901c198d16179b505b86600003611c5a57600088815260028f01602052604081208190559b505b505060019093019250611a96915050565b5060039190911b1796939550929350505050565b8051156001600160a01b0383161514611cab576040516326df4ccd60e01b815260040160405180910390fd5b6001600160a01b038216156105c8576001600160a01b0382163014611cf2576001600160a01b0382163b611cf257604051633ddc5cab60e21b815260040160405180910390fd5b6000826001600160a01b031682604051611d0c91906123b5565b600060405180830381855af49150503d8060008114611d47576040519150601f19603f3d011682016040523d82523d6000602084013e611d4c565b606091505b5050905080611460573d6000803e3d6000fd5b80356001600160e01b03198116811461102757600080fd5b600060208284031215611d8957600080fd5b611d9282611d5f565b9392505050565b80356001600160a01b038116811461102757600080fd5b60008083601f840112611dc257600080fd5b50813567ffffffffffffffff811115611dda57600080fd5b602083019150836020828501011115611df257600080fd5b9250929050565b600080600080600060608688031215611e1157600080fd5b853567ffffffffffffffff80821115611e2957600080fd5b818801915088601f830112611e3d57600080fd5b813581811115611e4c57600080fd5b8960208260051b8501011115611e6157600080fd5b60208301975080965050611e7760208901611d99565b94506040880135915080821115611e8d57600080fd5b50611e9a88828901611db0565b969995985093965092949392505050565b60008060408385031215611ebe57600080fd5b611ec783611d99565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b81811015611f165783516001600160a01b031683529284019291840191600101611ef1565b50909695505050505050565b600081518084526020808501945080840160005b83811015611f5c5781516001600160e01b03191687529582019590820190600101611f36565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611fd657888303603f19018552815180516001600160a01b03168452870151878401879052611fc387850182611f22565b9588019593505090860190600101611f8e565b509098975050505050505050565b600060208284031215611ff657600080fd5b611d9282611d99565b6020808252825182820181905260009190848201906040850190845b81811015611f165783516001600160e01b0319168352928401929184019160010161201b565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561207a5761207a612041565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156120a9576120a9612041565b604052919050565b600067ffffffffffffffff8211156120cb576120cb612041565b5060051b60200190565b60006120e86120e3846120b1565b612080565b83815260208082019190600586811b86013681111561210657600080fd5b865b818110156121fc57803567ffffffffffffffff808211156121295760008081fd5b818a0191506060823603121561213f5760008081fd5b612147612057565b61215083611d99565b815286830135600381106121645760008081fd5b818801526040838101358381111561217c5760008081fd5b939093019236601f85011261219357600092508283fd5b833592506121a36120e3846120b1565b83815292871b840188019288810190368511156121c05760008081fd5b948901945b848610156121e5576121d686611d5f565b825294890194908901906121c5565b918301919091525088525050948301948301612108565b5092979650505050505050565b634e487b7160e01b600052601160045260246000fd5b60006001820161223157612231612209565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff810361226457612264612209565b60010192915050565b60006020828403121561227f57600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b60005b838110156122b757818101518382015260200161229f565b50506000910152565b600081518084526122d881602086016020860161229c565b601f01601f19169290920160200192915050565b6000606080830181845280875180835260808601915060808160051b87010192506020808a016000805b8481101561238557898703607f19018652825180516001600160a01b03168852848101516003811061235657634e487b7160e01b84526021600452602484fd5b8886015260409081015190880189905261237289890182611f22565b9750509483019491830191600101612316565b5050506001600160a01b03891690870152505083810360408501526123aa81866122c0565b979650505050505050565b600082516123c781846020870161229c565b9190910192915050565b6000602082840312156123e357600080fd5b81518015158114611d9257600080fdfe68721c0bbf2c02a4d65000340d1370666be06a630022208d4baa9bd7a4b6fea8177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc93a2646970667358221220751905fa7cd544137dff4ce7e9fc230c133b64991687e4362da02260e7634aaf64736f6c6343000813003300000000000000000000000070287bd7a8e1b6deb354b0df11130b3be03d1ece0000000000000000000000000000000000000000000000000000000000000000

Deployed Bytecode

0x6080604052600436106101395760003560e01c80638ab5150a116100ab578063adfca15e1161006f578063adfca15e14610390578063cdffacc6146103bd578063eedc966a14610404578063f2fde38b14610424578063fb5b82d014610444578063fbacefce1461046457610140565b80638ab5150a146103115780638da5cb5b14610326578063913e77ad1461033b5780639142376514610350578063a89b11281461037057610140565b80633f4ba83a116100fd5780633f4ba83a1461027957806352ef6b2c1461028e5780635c975abb146102b057806379ba5097146102c55780637a0ed627146102da5780638456cb59146102fc57610140565b806301ffc9a71461019a578063093f0e27146101cf5780631f931c1c1461020c5780632c16f9261461022c5780632c4080591461024c57610140565b3661014057005b600061014a610484565b90506001600160a01b0381163b610174576040516321f27f0d60e21b815260040160405180910390fd5b3660008037600080366000845af43d6000803e808015610193573d6000f35b3d6000fd5b005b3480156101a657600080fd5b506101ba6101b5366004611d77565b610493565b60405190151581526020015b60405180910390f35b3480156101db57600080fd5b507f22ad9585a395edc8067b50da4778cafbb7fa2c4bbd7619fad6aeba403857fd745b6040519081526020016101c6565b34801561021857600080fd5b50610198610227366004611df9565b6104d6565b34801561023857600080fd5b50610198610247366004611eab565b610560565b34801561025857600080fd5b506102616105d7565b6040516001600160a01b0390911681526020016101c6565b34801561028557600080fd5b5061019861060a565b34801561029a57600080fd5b506102a361067d565b6040516101c69190611ed5565b3480156102bc57600080fd5b506101ba61082f565b3480156102d157600080fd5b5061019861084a565b3480156102e657600080fd5b506102ef61088b565b6040516101c69190611f67565b34801561030857600080fd5b50610198610cc2565b34801561031d57600080fd5b50610261610d34565b34801561033257600080fd5b50610261610d3e565b34801561034757600080fd5b50610261610d48565b34801561035c57600080fd5b5061019861036b366004611fe4565b610d7b565b34801561037c57600080fd5b5061019861038b366004611fe4565b610df4565b34801561039c57600080fd5b506103b06103ab366004611fe4565b610e36565b6040516101c69190611fff565b3480156103c957600080fd5b506102616103d8366004611d77565b6001600160e01b0319166000908152600080516020612434833981519152602052604090205460601c90565b34801561041057600080fd5b506101fe61041f366004611fe4565b610f91565b34801561043057600080fd5b5061019861043f366004611fe4565b61102c565b34801561045057600080fd5b5061019861045f366004611fe4565b61106e565b34801561047057600080fd5b5061019861047f366004611fe4565b6110b0565b600061048e61118d565b905090565b6001600160e01b0319811660009081527ffc606c433378e3a7e0a6a531deac289b66caa1b4aa8554fd4ab2c6f1570f92d8602052604081205460ff165b92915050565b6104de6111ee565b6001600160a01b0316336001600160a01b03161461050f57604051632f7a8ee160e01b815260040160405180910390fd5b61055961051c85876120d5565b8484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061121692505050565b5050505050565b6105686111ee565b6001600160a01b0316336001600160a01b03161461059957604051632f7a8ee160e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038316016105cc576105c833826113d2565b5050565b6105c8823383611465565b600061048e7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b6106126111ee565b6001600160a01b0316336001600160a01b03161461064357604051632f7a8ee160e01b815260040160405180910390fd5b6000805160206123f48339815191525460ff1661067357604051632ca4452d60e11b815260040160405180910390fd5b61067b611557565b565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff8111156106bc576106bc612041565b6040519080825280602002602001820160405280156106e5578160200160208202803683370190505b50915060008060005b600184015461ffff16821015610827576000818152600285016020526040812054905b600881101561081257836107248161221f565b600188015490955061ffff168511905061081257600581901b82901b6001600160e01b0319811660009081526020889052604081205460601c90805b888110156107b5578a818151811061077a5761077a612238565b60200260200101516001600160a01b0316836001600160a01b0316036107a357600191506107b5565b806107ad8161221f565b915050610760565b5080156107c457505050610800565b818a89815181106107d7576107d7612238565b6001600160a01b0390921660209283029190910190910152876107f98161221f565b9850505050505b8061080a8161221f565b915050610711565b5050808061081f9061221f565b9150506106ee565b505082525090565b600061048e6000805160206123f48339815191525460ff1690565b6108526115d4565b6001600160a01b0316336001600160a01b0316146108835760405163efd1052d60e01b815260040160405180910390fd5b61067b6115fc565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff8111156108ca576108ca612041565b60405190808252806020026020018201604052801561091057816020015b6040805180820190915260008152606060208201528152602001906001900390816108e85790505b50600182015490925060009061ffff1667ffffffffffffffff81111561093857610938612041565b604051908082528060200260200182016040528015610961578160200160208202803683370190505b50905060008060005b600185015461ffff16821015610c50576000818152600286016020526040812054905b6008811015610c3b57836109a08161221f565b600189015490955061ffff1685119050610c3b57600581901b82901b6001600160e01b0319811660009081526020899052604081205460601c90805b88811015610af957826001600160a01b03168c8281518110610a0057610a00612238565b6020026020010151600001516001600160a01b031603610ae757838c8281518110610a2d57610a2d612238565b6020026020010151602001518b8381518110610a4b57610a4b612238565b602002602001015160ff1681518110610a6657610a66612238565b60200260200101906001600160e01b03191690816001600160e01b0319168152505060ff8a8281518110610a9c57610a9c612238565b602002602001015160ff1610610ab157600080fd5b898181518110610ac357610ac3612238565b602002602001018051809190610ad89061224e565b60ff1690525060019150610af9565b80610af18161221f565b9150506109dc565b508015610b0857505050610c29565b818b8981518110610b1b57610b1b612238565b60209081029190910101516001600160a01b03909116905260018a015461ffff1667ffffffffffffffff811115610b5457610b54612041565b604051908082528060200260200182016040528015610b7d578160200160208202803683370190505b508b8981518110610b9057610b90612238565b602002602001015160200181905250828b8981518110610bb257610bb2612238565b602002602001015160200151600081518110610bd057610bd0612238565b60200260200101906001600160e01b03191690816001600160e01b031916815250506001898981518110610c0657610c06612238565b60ff9092166020928302919091019091015287610c228161221f565b9850505050505b80610c338161221f565b91505061098d565b50508080610c489061221f565b91505061096a565b5060005b82811015610cb7576000848281518110610c7057610c70612238565b602002602001015160ff1690506000878381518110610c9157610c91612238565b602002602001015160200151905081815250508080610caf9061221f565b915050610c54565b508185525050505090565b610cca6111ee565b6001600160a01b0316336001600160a01b031614610cfb57604051632f7a8ee160e01b815260040160405180910390fd5b6000805160206123f48339815191525460ff1615610d2c576040516302ca8ced60e11b815260040160405180910390fd5b61067b611636565b600061048e6115d4565b600061048e6111ee565b60007f8135b9b8d3411dab68efe82c12999875113f270399aa3b0126860dde293ca8f35b546001600160a01b0316919050565b610d836111ee565b6001600160a01b0316336001600160a01b031614610db457604051632f7a8ee160e01b815260040160405180910390fd5b7f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc9680546001600160a01b0319166001600160a01b03831617905550565b50565b610dfc6111ee565b6001600160a01b0316336001600160a01b031614610e2d57604051632f7a8ee160e01b815260040160405180910390fd5b610df1816116b1565b600080516020612414833981519152546060906000805160206124348339815191529061ffff1667ffffffffffffffff811115610e7557610e75612041565b604051908082528060200260200182016040528015610e9e578160200160208202803683370190505b50915060008060005b600184015461ffff16821015610f87576000818152600285016020526040812054905b6008811015610f725783610edd8161221f565b600188015490955061ffff1685119050610f7257600581901b82901b6001600160e01b0319811660009081526020889052604090205460601c6001600160a01b038a1603610f5f5780888781518110610f3857610f38612238565b6001600160e01b03199092166020928302919091019091015285610f5b8161221f565b9650505b5080610f6a8161221f565b915050610eca565b50508080610f7f9061221f565b915050610ea7565b5050825250919050565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03831601610fbf575047919050565b6040516370a0823160e01b81523060048201526001600160a01b038316906370a0823190602401602060405180830381865afa158015611003573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104d0919061226d565b919050565b6110346111ee565b6001600160a01b0316336001600160a01b03161461106557604051632f7a8ee160e01b815260040160405180910390fd5b610df18161172b565b6110766111ee565b6001600160a01b0316336001600160a01b0316146110a757604051632f7a8ee160e01b815260040160405180910390fd5b610df18161176e565b6110b86111ee565b6001600160a01b0316336001600160a01b0316146110e957604051632f7a8ee160e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0382160161111857610df133476113d2565b6040516370a0823160e01b8152306004820152610df190829033906001600160a01b038316906370a0823190602401602060405180830381865afa158015611164573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611188919061226d565b611465565b600080356001600160e01b0319168152600080516020612434833981519152602052604090205460601c806111eb57507f177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc96546001600160a01b031690565b90565b60007f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f671680460610d6c565b600080516020612414833981519152546000805160206124348339815191529061ffff8116908190600090600716156112615750600381901c60009081526002840160205260409020545b60005b875181101561134657600088828151811061128157611281612238565b602002602001015190506000816020015190508160400151516000036112ba5760405163eb6c3aeb60e01b815260040160405180910390fd5b60008160028111156112ce576112ce612286565b036112e9576112df878686856117d7565b909550935061133c565b60018160028111156112fd576112fd612286565b036113115761130c8783611916565b61133c565b600281600281111561132557611325612286565b0361133c5761133687868685611a5c565b90955093505b5050600101611264565b508282146113625760018401805461ffff191661ffff84161790555b600782161561138457600382901c600090815260028501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738787876040516113b7939291906122ec565b60405180910390a16113c98686611c7f565b50505050505050565b604080516000808252602082019092526001600160a01b0384169083906040516113fc91906123b5565b60006040518083038185875af1925050503d8060008114611439576040519150601f19603f3d011682016040523d82523d6000602084013e61143e565b606091505b505090508061146057604051632e05b05360e21b815260040160405180910390fd5b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180516001600160e01b031663a9059cbb60e01b17905291516000928392908716916114c191906123b5565b6000604051808303816000865af19150503d80600081146114fe576040519150601f19603f3d011682016040523d82523d6000602084013e611503565b606091505b5091509150600082801561152f57508151158061152f57508180602001905181019061152f91906123d1565b90508061154f57604051632fdb1b7f60e11b815260040160405180910390fd5b505050505050565b6000805160206123f48339815191525460ff1661158757604051632ca4452d60e11b815260040160405180910390fd5b6000805160206123f4833981519152805460ff191690556040513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa906020015b60405180910390a1565b60007f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce6617890610d6c565b611605336116b1565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319169055565b6000805160206123f48339815191525460ff1615611667576040516302ca8ced60e11b815260040160405180910390fd5b6000805160206123f4833981519152805460ff191660011790556040513381527f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258906020016115ca565b7f8a22373512790c48b83a1fe2efdd2888d4a917bcdc24d0adf63e60f67168046080546040516001600160a01b038481169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a380546001600160a01b0319166001600160a01b0392909216919091179055565b7f24aa1f7b31fd188a8d3ecfb06bc55c806040e59b03bd4396283442fce661789080546001600160a01b0319166001600160a01b038316179055610df181818181565b7f8135b9b8d3411dab68efe82c12999875113f270399aa3b0126860dde293ca8f380546001600160a01b0319166001600160a01b0383169081179091556040517f0cc5437d7c9c1d9eab549acbb533eea3e9868e9443dd75309ed5820b33a3774e90600090a250565b805160009081906001600160a01b031630148015906117ff575082516001600160a01b03163b155b1561181d57604051633ddc5cab60e21b815260040160405180910390fd5b60005b8360400151518110156119095760008460400151828151811061184557611845612238565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c1561189157604051634923a77160e11b815260040160405180910390fd5b85516001600160e01b0319838116600081815260208d90526040902060609390931b6001600160601b0319168b1790925560058a901b60e090811692831c91831c199990991617978190036118fa57600389901c600090815260028b0160205260408120989098555b50505060019586019501611820565b5093959294509192505050565b80516001600160a01b03163b61193f57604051633ddc5cab60e21b815260040160405180910390fd5b60005b8160400151518110156114605760008260400151828151811061196757611967612238565b6020908102919091018101516001600160e01b03198116600090815291869052604090912054909150606081901c806119b3576040516337e25a9760e11b815260040160405180910390fd5b306001600160a01b038216036119dc5760405163e983573160e01b815260040160405180910390fd5b84600001516001600160a01b0316816001600160a01b031603611a12576040516330baabf360e11b815260040160405180910390fd5b5083516001600160e01b031992909216600090815260208690526040902060609290921b6001600160601b0319166bffffffffffffffffffffffff91909116179055600101611942565b805160009081906001600160a01b031615611a8a57604051633ab3490960e21b815260040160405180910390fd5b600385901c6007861660005b856040015151811015611c6b57600086604001518281518110611abb57611abb612238565b6020908102919091018101516001600160e01b031981166000908152918c9052604090912054909150606081901c611b06576040516337e25a9760e11b815260040160405180910390fd5b30606082901c03611b2a5760405163e983573160e01b815260040160405180910390fd5b6000899003611b5657600019909401600081815260028c01602052604090205498509360079350611b5e565b600019909301925b600584901b89901b6000806001600160e01b031980841690861614611bb5576001600160e01b03198316600090815260208f90526040902080546001600160601b0319166bffffffffffffffffffffffff86161790555b50506001600160e01b03198316600090815260208d90526040812055611fff600383901c1660e0600584901b16878214611c1857600082815260028f016020526040902080546001600160e01b031980841c19909116908516831c179055611c3c565b80836001600160e01b031916901c816001600160e01b031960001b901c198d16179b505b86600003611c5a57600088815260028f01602052604081208190559b505b505060019093019250611a96915050565b5060039190911b1796939550929350505050565b8051156001600160a01b0383161514611cab576040516326df4ccd60e01b815260040160405180910390fd5b6001600160a01b038216156105c8576001600160a01b0382163014611cf2576001600160a01b0382163b611cf257604051633ddc5cab60e21b815260040160405180910390fd5b6000826001600160a01b031682604051611d0c91906123b5565b600060405180830381855af49150503d8060008114611d47576040519150601f19603f3d011682016040523d82523d6000602084013e611d4c565b606091505b5050905080611460573d6000803e3d6000fd5b80356001600160e01b03198116811461102757600080fd5b600060208284031215611d8957600080fd5b611d9282611d5f565b9392505050565b80356001600160a01b038116811461102757600080fd5b60008083601f840112611dc257600080fd5b50813567ffffffffffffffff811115611dda57600080fd5b602083019150836020828501011115611df257600080fd5b9250929050565b600080600080600060608688031215611e1157600080fd5b853567ffffffffffffffff80821115611e2957600080fd5b818801915088601f830112611e3d57600080fd5b813581811115611e4c57600080fd5b8960208260051b8501011115611e6157600080fd5b60208301975080965050611e7760208901611d99565b94506040880135915080821115611e8d57600080fd5b50611e9a88828901611db0565b969995985093965092949392505050565b60008060408385031215611ebe57600080fd5b611ec783611d99565b946020939093013593505050565b6020808252825182820181905260009190848201906040850190845b81811015611f165783516001600160a01b031683529284019291840191600101611ef1565b50909695505050505050565b600081518084526020808501945080840160005b83811015611f5c5781516001600160e01b03191687529582019590820190600101611f36565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015611fd657888303603f19018552815180516001600160a01b03168452870151878401879052611fc387850182611f22565b9588019593505090860190600101611f8e565b509098975050505050505050565b600060208284031215611ff657600080fd5b611d9282611d99565b6020808252825182820181905260009190848201906040850190845b81811015611f165783516001600160e01b0319168352928401929184019160010161201b565b634e487b7160e01b600052604160045260246000fd5b6040516060810167ffffffffffffffff8111828210171561207a5761207a612041565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156120a9576120a9612041565b604052919050565b600067ffffffffffffffff8211156120cb576120cb612041565b5060051b60200190565b60006120e86120e3846120b1565b612080565b83815260208082019190600586811b86013681111561210657600080fd5b865b818110156121fc57803567ffffffffffffffff808211156121295760008081fd5b818a0191506060823603121561213f5760008081fd5b612147612057565b61215083611d99565b815286830135600381106121645760008081fd5b818801526040838101358381111561217c5760008081fd5b939093019236601f85011261219357600092508283fd5b833592506121a36120e3846120b1565b83815292871b840188019288810190368511156121c05760008081fd5b948901945b848610156121e5576121d686611d5f565b825294890194908901906121c5565b918301919091525088525050948301948301612108565b5092979650505050505050565b634e487b7160e01b600052601160045260246000fd5b60006001820161223157612231612209565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff810361226457612264612209565b60010192915050565b60006020828403121561227f57600080fd5b5051919050565b634e487b7160e01b600052602160045260246000fd5b60005b838110156122b757818101518382015260200161229f565b50506000910152565b600081518084526122d881602086016020860161229c565b601f01601f19169290920160200192915050565b6000606080830181845280875180835260808601915060808160051b87010192506020808a016000805b8481101561238557898703607f19018652825180516001600160a01b03168852848101516003811061235657634e487b7160e01b84526021600452602484fd5b8886015260409081015190880189905261237289890182611f22565b9750509483019491830191600101612316565b5050506001600160a01b03891690870152505083810360408501526123aa81866122c0565b979650505050505050565b600082516123c781846020870161229c565b9190910192915050565b6000602082840312156123e357600080fd5b81518015158114611d9257600080fdfe68721c0bbf2c02a4d65000340d1370666be06a630022208d4baa9bd7a4b6fea8177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc94177481ac65e4292921c69f62d1cc7f57541261e5d61c8175cf4e36a01c9bfc93a2646970667358221220751905fa7cd544137dff4ce7e9fc230c133b64991687e4362da02260e7634aaf64736f6c63430008130033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

00000000000000000000000070287bd7a8e1b6deb354b0df11130b3be03d1ece0000000000000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : _collector (address): 0x70287bd7A8e1b6deb354b0dF11130b3be03D1Ece
Arg [1] : _owner (address): 0x0000000000000000000000000000000000000000

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000070287bd7a8e1b6deb354b0df11130b3be03d1ece
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000000


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.