ETH Price: $2,479.04 (-0.06%)

Token

GONDI_USER_VAULT (GUV)
 

Overview

Max Total Supply

0 GUV

Holders

294

Market

Volume (24H)

N/A

Min Price (24H)

N/A

Max Price (24H)

N/A
Balance
1 GUV
0x75444037dffce5c12ea4c27b56cc806c8dcf2c45
Loading...
Loading
Loading...
Loading
Loading...
Loading

Click here to update the token information / general information
# Exchange Pair Price  24H Volume % Volume
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.

Contract Source Code Verified (Exact Match)

Contract Name:
UserVault

Compiler Version
v0.8.21+commit.d9974bed

Optimization Enabled:
Yes with 20 runs

Other Settings:
paris EvmVersion, GNU AGPLv3 license
File 1 of 16 : UserVault.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.21;

import "@openzeppelin/utils/Strings.sol";
import "@solmate/auth/Owned.sol";
import "@solmate/tokens/ERC721.sol";
import "@solmate/tokens/ERC1155.sol";
import "@solmate/utils/SafeTransferLib.sol";

import "../interfaces/IOldERC721.sol";
import "../interfaces/IUserVault.sol";
import "./AddressManager.sol";

/// @title Auction Loan Liquidator
/// @author Florida St
/// @notice NFTs that represent bundles.
/// @dev This vault does not support rebasing tokens. Rebasing tokens can cause accounting 
/// @dev errors since the vault tracks balances internally and won't update when rebases occur.

contract UserVault is
    ERC721,
    ERC721TokenReceiver,
    ERC1155TokenReceiver,
    IUserVault
{
    using SafeTransferLib for ERC20;

    string private constant _BASE_URI = "https://gondi.xyz/user_vaults/";
    uint256 private _nextId = 0;

    address public constant ETH =
        address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);

    /// @notice IDs that were burnt are pending withdrawal
    mapping(uint256 vaultId => address claimer) _readyForWithdrawal;

    /// @notice NFT balances for a given vault: collection => (tokenId => vaultId)
    mapping(address collection => mapping(uint256 tokenId => uint256 vaultId)) _vaultERC721s;

    /// @notice ERC20 balances for a given vault: token => (vaultId => amount). address(0) = ETH
    mapping(address token => mapping(uint256 vaultId => uint256 amount)) _vaultERC20s;

    /// @notice ERC1155 balances for a given vault: token => (vaultId => amount). address(0) = ETH
    mapping(address token => mapping(uint256 tokenId => mapping(uint256 vaultId => uint256 amount))) _vaultERC1155s;

    AddressManager private immutable _currencyManager;

    AddressManager private immutable _collectionManager;

    event ERC721Deposited(uint256 vaultId, address collection, uint256 tokenId);

    event ERC20Deposited(uint256 vaultId, address token, uint256 amount);

    event ERC1155Deposited(
        uint256 vaultId,
        address token,
        uint256 tokenId,
        uint256 amount
    );

    event ERC721Withdrawn(uint256 vaultId, address collection, uint256 tokenId);

    event ERC20Withdrawn(uint256 vaultId, address token, uint256 amount);

    event ERC1155Withdrawn(
        uint256 vaultId,
        address token,
        uint256 tokenId,
        uint256 amount
    );

    error CurrencyNotWhitelistedError();

    error CollectionNotWhitelistedError();

    error LengthMismatchError();

    error NotApprovedError(uint256 vaultId);

    error WithdrawingETHError();

    error WrongMethodError();

    error AssetNotOwnedError();

    error VaultNotExistsError();

    error InvalidCallerError();

    /// @param currencyManager Address of the CurrencyManager contract.
    /// @param collectionManager Address of the CollectionManager contract.
    constructor(
        address currencyManager,
        address collectionManager
    ) ERC721("GONDI_USER_VAULT", "GUV") {
        _currencyManager = AddressManager(currencyManager);
        _collectionManager = AddressManager(collectionManager);
    }

    /// @inheritdoc IUserVault
    function mint() external returns (uint256) {
        uint256 _vaultId;
        unchecked {
            _vaultId = ++_nextId;
        }
        _mint(msg.sender, _vaultId);
        return _vaultId;
    }

    /// @inheritdoc IUserVault
    function burn(uint256 _vaultId, address _assetRecipient) external {
        _thisBurn(_vaultId, _assetRecipient);
    }

    /// @inheritdoc IUserVault
    function burnAndWithdraw(
        uint256 _vaultId,
        address[] calldata _collections,
        uint256[] calldata _tokenIds,
        address[] calldata _tokens,
        address[] calldata _erc1155Tokens,
        uint256[] calldata _erc1155TokensIds
    ) external {
        _thisBurn(_vaultId, msg.sender);
        uint256 totalCollections = _collections.length;
        if (totalCollections != _tokenIds.length) {
            revert LengthMismatchError();
        }
        for (uint256 i = 0; i < totalCollections; ) {
            _withdrawERC721(_vaultId, _collections[i], _tokenIds[i]);
            unchecked {
                ++i;
            }
        }
        uint256 totalTokens = _tokens.length;
        for (uint256 i = 0; i < totalTokens; ) {
            _withdrawERC20(_vaultId, _tokens[i]);
            unchecked {
                ++i;
            }
        }
        uint256 totalERC1155Tokens = _erc1155Tokens.length;
        for (uint256 i = 0; i < totalERC1155Tokens; ) {
            _withdrawERC1155(_vaultId, _erc1155Tokens[i], _erc1155TokensIds[i]);
            unchecked {
                ++i;
            }
        }
        _withdrawEth(_vaultId);
    }

    function ERC721OwnerOf(
        address _collection,
        uint256 _tokenId
    ) external view returns (uint256) {
        return _vaultERC721s[_collection][_tokenId];
    }

    function ERC20BalanceOf(
        uint256 _vaultId,
        address _token
    ) external view returns (uint256) {
        return _vaultERC20s[_token][_vaultId];
    }

    function ERC1155BalanceOf(
        uint256 _vaultId,
        address _token,
        uint256 _tokenId
    ) external view returns (uint256) {
        return _vaultERC1155s[_token][_tokenId][_vaultId];
    }

    /// @inheritdoc IUserVault
    function depositERC721(
        uint256 _vaultId,
        address _collection,
        uint256 _tokenId
    ) external {
        _vaultExists(_vaultId);

        if (!_collectionManager.isWhitelisted(_collection)) {
            revert CollectionNotWhitelistedError();
        }
        _depositERC721(msg.sender, _vaultId, _collection, _tokenId);
    }

    /// @inheritdoc IUserVault
    /// @dev Read `depositERC721`.
    function depositERC721s(
        uint256 _vaultId,
        address _collection,
        uint256[] calldata _tokenIds
    ) external {
        _vaultExists(_vaultId);
        if (!_collectionManager.isWhitelisted(_collection)) {
            revert CollectionNotWhitelistedError();
        }
        uint256 totalTokens = _tokenIds.length;
        for (uint256 i = 0; i < totalTokens; ) {
            _depositERC721(msg.sender, _vaultId, _collection, _tokenIds[i]);
            unchecked {
                ++i;
            }
        }
    }

    /// @inheritdoc IUserVault
    /// @dev Read `depositERC721`.
    function depositERC20(
        uint256 _vaultId,
        address _token,
        uint256 _amount
    ) external {
        _vaultExists(_vaultId);

        if (_token == ETH) {
            revert WrongMethodError();
        }
        _depositERC20(msg.sender, _vaultId, _token, _amount);
    }

    /// @inheritdoc IUserVault
    /// @dev Read `depositERC1155`.
    function depositERC1155(
        uint256 _vaultId,
        address _token,
        uint256 _tokenId,
        uint256 _amount
    ) external {
        _vaultExists(_vaultId);

        if (!_collectionManager.isWhitelisted(_token)) {
            revert CollectionNotWhitelistedError();
        }

        _depositERC1155(msg.sender, _vaultId, _token, _tokenId, _amount);
    }

    /// @inheritdoc IUserVault
    /// @dev Read `depositERC1155s`.
    function depositERC1155s(
        uint256 _vaultId,
        address _collection,
        uint256[] calldata _tokenIds,
        uint256[] calldata _amounts
    ) external {
        _vaultExists(_vaultId);
        if (!_collectionManager.isWhitelisted(_collection)) {
            revert CollectionNotWhitelistedError();
        }
        uint256 totalTokens = _tokenIds.length;
        for (uint256 i = 0; i < totalTokens; ) {
            _depositERC1155(
                msg.sender,
                _vaultId,
                _collection,
                _tokenIds[i],
                _amounts[i]
            );
            unchecked {
                ++i;
            }
        }
    }

    /// @inheritdoc IUserVault
    /// @dev Read `depositERC721`.
    function depositEth(uint256 _vaultId) external payable {
        _vaultExists(_vaultId);

        _vaultERC20s[ETH][_vaultId] += msg.value;

        emit ERC20Deposited(_vaultId, ETH, msg.value);
    }

    /// @inheritdoc IUserVault
    function withdrawERC721(
        uint256 _vaultId,
        address _collection,
        uint256 _tokenId
    ) external {
        _withdrawERC721(_vaultId, _collection, _tokenId);
    }

    /// @inheritdoc IUserVault
    function withdrawERC721s(
        uint256 _vaultId,
        address[] calldata _collections,
        uint256[] calldata _tokenIds
    ) external {
        if (_collections.length != _tokenIds.length) {
            revert LengthMismatchError();
        }
        uint256 totalCollections = _collections.length;
        for (uint256 i = 0; i < totalCollections; ) {
            _withdrawERC721(_vaultId, _collections[i], _tokenIds[i]);
            unchecked {
                ++i;
            }
        }
    }

    /// @inheritdoc IUserVault
    function withdrawERC20(uint256 _vaultId, address _token) external {
        _withdrawERC20(_vaultId, _token);
    }

    /// @inheritdoc IUserVault
    function withdrawERC20s(
        uint256 _vaultId,
        address[] calldata _tokens
    ) external {
        for (uint256 i = 0; i < _tokens.length; ) {
            _withdrawERC20(_vaultId, _tokens[i]);
            unchecked {
                ++i;
            }
        }
    }

    /// @inheritdoc IUserVault
    function withdrawERC1155(
        uint256 _vaultId,
        address _token,
        uint256 _tokenId
    ) external {
        _withdrawERC1155(_vaultId, _token, _tokenId);
    }

    /// @inheritdoc IUserVault
    function withdrawERC1155s(
        uint256 _vaultId,
        address[] calldata _tokens,
        uint256[] calldata _tokenIds
    ) external {
        if (_tokens.length != _tokenIds.length) {
            revert LengthMismatchError();
        }
        uint256 totalCollections = _tokens.length;
        for (uint256 i = 0; i < totalCollections; ) {
            _withdrawERC1155(_vaultId, _tokens[i], _tokenIds[i]);
            unchecked {
                ++i;
            }
        }
    }

    /// @inheritdoc IUserVault
    function withdrawEth(uint256 _vaultId) external {
        _withdrawEth(_vaultId);
    }

    /// @inheritdoc ERC721
    function tokenURI(
        uint256 _vaultId
    ) public pure override returns (string memory) {
        return string.concat(_BASE_URI, Strings.toString(_vaultId));
    }

    function _depositERC721(
        address _depositor,
        uint256 _vaultId,
        address _collection,
        uint256 _tokenId
    ) private {
        ERC721(_collection).transferFrom(_depositor, address(this), _tokenId);

        _vaultERC721s[_collection][_tokenId] = _vaultId;

        emit ERC721Deposited(_vaultId, _collection, _tokenId);
    }

    function _depositERC20(
        address _depositor,
        uint256 _vaultId,
        address _token,
        uint256 _amount
    ) private {
        if (!_currencyManager.isWhitelisted(_token)) {
            revert CurrencyNotWhitelistedError();
        }
        ERC20(_token).safeTransferFrom(_depositor, address(this), _amount);

        _vaultERC20s[_token][_vaultId] += _amount;
        emit ERC20Deposited(_vaultId, _token, _amount);
    }

    function _depositERC1155(
        address _depositor,
        uint256 _vaultId,
        address _token,
        uint256 _tokenId,
        uint256 _amount
    ) private {
        ERC1155(_token).safeTransferFrom(
            _depositor,
            address(this),
            _tokenId,
            _amount,
            ""
        );

        _vaultERC1155s[_token][_tokenId][_vaultId] += _amount;
        emit ERC1155Deposited(_vaultId, _token, _tokenId, _amount);
    }

    /// @dev We are allowing anyone to deposit NFTs into a vault (not just the owner). Because of this we call transferFrom
    /// and not safeTransferFrom to avoid someone locking assets by transferring an ERC721 with the hook corrupted (we do
    /// have a whitelist to avoid this but being extra cautious.)
    function _withdrawERC721(
        uint256 _vaultId,
        address _collection,
        uint256 _tokenId
    ) private {
        _onlyReadyForWithdrawal(_vaultId);

        if (_vaultERC721s[_collection][_tokenId] != _vaultId) {
            revert AssetNotOwnedError();
        }
        ERC721(_collection).transferFrom(address(this), msg.sender, _tokenId);

        delete _vaultERC721s[_collection][_tokenId];

        emit ERC721Withdrawn(_vaultId, _collection, _tokenId);
    }

    function _withdrawERC20(uint256 _vaultId, address _token) private {
        _onlyReadyForWithdrawal(_vaultId);

        uint256 amount = _vaultERC20s[_token][_vaultId];
        if (amount == 0) {
            return;
        }
        delete _vaultERC20s[_token][_vaultId];

        ERC20(_token).safeTransfer(msg.sender, amount);

        emit ERC20Withdrawn(_vaultId, _token, amount);
    }

    function _withdrawERC1155(
        uint256 _vaultId,
        address _token,
        uint256 _tokenId
    ) private {
        _onlyReadyForWithdrawal(_vaultId);

        uint256 amount = _vaultERC1155s[_token][_tokenId][_vaultId];
        if (amount == 0) {
            return;
        }
        delete _vaultERC1155s[_token][_tokenId][_vaultId];

        ERC1155(_token).safeTransferFrom(
            address(this),
            msg.sender,
            _tokenId,
            amount,
            ""
        );

        emit ERC1155Withdrawn(_vaultId, _token, _tokenId, amount);
    }

    function _thisBurn(uint256 _vaultId, address _assetRecipient) private {
        _onlyApproved(_vaultId);

        _burn(_vaultId);
        _readyForWithdrawal[_vaultId] = _assetRecipient;
    }

    function _withdrawEth(uint256 _vaultId) private {
        _onlyReadyForWithdrawal(_vaultId);

        uint256 amount = _vaultERC20s[ETH][_vaultId];
        if (amount == 0) {
            return;
        }
        delete _vaultERC20s[ETH][_vaultId];

        (bool sent, ) = payable(msg.sender).call{value: amount}("");
        if (!sent) {
            revert WithdrawingETHError();
        }

        emit ERC20Withdrawn(_vaultId, ETH, amount);
    }

    function _vaultExists(uint256 _vaultId) private view {
        bytes4 errorSelector = VaultNotExistsError.selector;
        address owner = _ownerOf[_vaultId];
        assembly {
            if iszero(owner) {
                mstore(0x00, errorSelector)
                revert(0x00, 0x04)
            }
        }
    }

    function _onlyApproved(uint256 _vaultId) private view {
        if (
            msg.sender != ownerOf(_vaultId) &&
            !isApprovedForAll[ownerOf(_vaultId)][msg.sender] &&
            getApproved[_vaultId] != msg.sender
        ) {
            revert NotApprovedError(_vaultId);
        }
    }

    function _onlyReadyForWithdrawal(uint256 _vaultId) private view {
        if (_readyForWithdrawal[_vaultId] != msg.sender) {
            revert NotApprovedError(_vaultId);
        }
    }
}

File 2 of 16 : Strings.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)

pragma solidity ^0.8.20;

import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant HEX_DIGITS = "0123456789abcdef";
    uint8 private constant ADDRESS_LENGTH = 20;

    /**
     * @dev The `value` string doesn't fit in the specified `length`.
     */
    error StringsInsufficientHexLength(uint256 value, uint256 length);

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        unchecked {
            uint256 length = Math.log10(value) + 1;
            string memory buffer = new string(length);
            uint256 ptr;
            /// @solidity memory-safe-assembly
            assembly {
                ptr := add(buffer, add(32, length))
            }
            while (true) {
                ptr--;
                /// @solidity memory-safe-assembly
                assembly {
                    mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
                }
                value /= 10;
                if (value == 0) break;
            }
            return buffer;
        }
    }

    /**
     * @dev Converts a `int256` to its ASCII `string` decimal representation.
     */
    function toStringSigned(int256 value) internal pure returns (string memory) {
        return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        unchecked {
            return toHexString(value, Math.log256(value) + 1);
        }
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        uint256 localValue = value;
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = HEX_DIGITS[localValue & 0xf];
            localValue >>= 4;
        }
        if (localValue != 0) {
            revert StringsInsufficientHexLength(value, length);
        }
        return string(buffer);
    }

    /**
     * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
     * representation.
     */
    function toHexString(address addr) internal pure returns (string memory) {
        return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
    }

    /**
     * @dev Returns true if the two strings are equal.
     */
    function equal(string memory a, string memory b) internal pure returns (bool) {
        return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
    }
}

File 3 of 16 : Owned.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event OwnershipTransferred(address indexed user, address indexed newOwner);

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

File 4 of 16 : ERC721.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern, minimalist, and gas efficient ERC-721 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 indexed id);

    event Approval(address indexed owner, address indexed spender, uint256 indexed id);

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    /*//////////////////////////////////////////////////////////////
                         METADATA STORAGE/LOGIC
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    function tokenURI(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                      ERC721 BALANCE/OWNER STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) internal _ownerOf;

    mapping(address => uint256) internal _balanceOf;

    function ownerOf(uint256 id) public view virtual returns (address owner) {
        require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
    }

    function balanceOf(address owner) public view virtual returns (uint256) {
        require(owner != address(0), "ZERO_ADDRESS");

        return _balanceOf[owner];
    }

    /*//////////////////////////////////////////////////////////////
                         ERC721 APPROVAL STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(uint256 => address) public getApproved;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol) {
        name = _name;
        symbol = _symbol;
    }

    /*//////////////////////////////////////////////////////////////
                              ERC721 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 id) public virtual {
        address owner = _ownerOf[id];

        require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");

        getApproved[id] = spender;

        emit Approval(owner, spender, id);
    }

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function transferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        require(from == _ownerOf[id], "WRONG_FROM");

        require(to != address(0), "INVALID_RECIPIENT");

        require(
            msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id],
            "NOT_AUTHORIZED"
        );

        // Underflow of the sender's balance is impossible because we check for
        // ownership above and the recipient's balance can't realistically overflow.
        unchecked {
            _balanceOf[from]--;

            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        delete getApproved[id];

        emit Transfer(from, to, id);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        bytes calldata data
    ) public virtual {
        transferFrom(from, to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721
            interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 id) internal virtual {
        require(to != address(0), "INVALID_RECIPIENT");

        require(_ownerOf[id] == address(0), "ALREADY_MINTED");

        // Counter overflow is incredibly unrealistic.
        unchecked {
            _balanceOf[to]++;
        }

        _ownerOf[id] = to;

        emit Transfer(address(0), to, id);
    }

    function _burn(uint256 id) internal virtual {
        address owner = _ownerOf[id];

        require(owner != address(0), "NOT_MINTED");

        // Ownership check above ensures no underflow.
        unchecked {
            _balanceOf[owner]--;
        }

        delete _ownerOf[id];

        delete getApproved[id];

        emit Transfer(owner, address(0), id);
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL SAFE MINT LOGIC
    //////////////////////////////////////////////////////////////*/

    function _safeMint(address to, uint256 id) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _safeMint(
        address to,
        uint256 id,
        bytes memory data
    ) internal virtual {
        _mint(to, id);

        require(
            to.code.length == 0 ||
                ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) ==
                ERC721TokenReceiver.onERC721Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }
}

/// @notice A generic interface for a contract which properly accepts ERC721 tokens.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol)
abstract contract ERC721TokenReceiver {
    function onERC721Received(
        address,
        address,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC721TokenReceiver.onERC721Received.selector;
    }
}

File 5 of 16 : ERC1155.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Minimalist and gas efficient standard ERC1155 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event TransferSingle(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256 id,
        uint256 amount
    );

    event TransferBatch(
        address indexed operator,
        address indexed from,
        address indexed to,
        uint256[] ids,
        uint256[] amounts
    );

    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

    event URI(string value, uint256 indexed id);

    /*//////////////////////////////////////////////////////////////
                             ERC1155 STORAGE
    //////////////////////////////////////////////////////////////*/

    mapping(address => mapping(uint256 => uint256)) public balanceOf;

    mapping(address => mapping(address => bool)) public isApprovedForAll;

    /*//////////////////////////////////////////////////////////////
                             METADATA LOGIC
    //////////////////////////////////////////////////////////////*/

    function uri(uint256 id) public view virtual returns (string memory);

    /*//////////////////////////////////////////////////////////////
                              ERC1155 LOGIC
    //////////////////////////////////////////////////////////////*/

    function setApprovalForAll(address operator, bool approved) public virtual {
        isApprovedForAll[msg.sender][operator] = approved;

        emit ApprovalForAll(msg.sender, operator, approved);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 id,
        uint256 amount,
        bytes calldata data
    ) public virtual {
        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        balanceOf[from][id] -= amount;
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, from, to, id, amount);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function safeBatchTransferFrom(
        address from,
        address to,
        uint256[] calldata ids,
        uint256[] calldata amounts,
        bytes calldata data
    ) public virtual {
        require(ids.length == amounts.length, "LENGTH_MISMATCH");

        require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED");

        // Storing these outside the loop saves ~15 gas per iteration.
        uint256 id;
        uint256 amount;

        for (uint256 i = 0; i < ids.length; ) {
            id = ids[i];
            amount = amounts[i];

            balanceOf[from][id] -= amount;
            balanceOf[to][id] += amount;

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, from, to, ids, amounts);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function balanceOfBatch(address[] calldata owners, uint256[] calldata ids)
        public
        view
        virtual
        returns (uint256[] memory balances)
    {
        require(owners.length == ids.length, "LENGTH_MISMATCH");

        balances = new uint256[](owners.length);

        // Unchecked because the only math done is incrementing
        // the array index counter which cannot possibly overflow.
        unchecked {
            for (uint256 i = 0; i < owners.length; ++i) {
                balances[i] = balanceOf[owners[i]][ids[i]];
            }
        }
    }

    /*//////////////////////////////////////////////////////////////
                              ERC165 LOGIC
    //////////////////////////////////////////////////////////////*/

    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return
            interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165
            interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155
            interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(
        address to,
        uint256 id,
        uint256 amount,
        bytes memory data
    ) internal virtual {
        balanceOf[to][id] += amount;

        emit TransferSingle(msg.sender, address(0), to, id, amount);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) ==
                    ERC1155TokenReceiver.onERC1155Received.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _batchMint(
        address to,
        uint256[] memory ids,
        uint256[] memory amounts,
        bytes memory data
    ) internal virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[to][ids[i]] += amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, address(0), to, ids, amounts);

        require(
            to.code.length == 0
                ? to != address(0)
                : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) ==
                    ERC1155TokenReceiver.onERC1155BatchReceived.selector,
            "UNSAFE_RECIPIENT"
        );
    }

    function _batchBurn(
        address from,
        uint256[] memory ids,
        uint256[] memory amounts
    ) internal virtual {
        uint256 idsLength = ids.length; // Saves MLOADs.

        require(idsLength == amounts.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < idsLength; ) {
            balanceOf[from][ids[i]] -= amounts[i];

            // An array can't have a total length
            // larger than the max uint256 value.
            unchecked {
                ++i;
            }
        }

        emit TransferBatch(msg.sender, from, address(0), ids, amounts);
    }

    function _burn(
        address from,
        uint256 id,
        uint256 amount
    ) internal virtual {
        balanceOf[from][id] -= amount;

        emit TransferSingle(msg.sender, from, address(0), id, amount);
    }
}

/// @notice A generic interface for a contract which properly accepts ERC1155 tokens.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol)
abstract contract ERC1155TokenReceiver {
    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] calldata,
        uint256[] calldata,
        bytes calldata
    ) external virtual returns (bytes4) {
        return ERC1155TokenReceiver.onERC1155BatchReceived.selector;
    }
}

File 6 of 16 : SafeTransferLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {ERC20} from "../tokens/ERC20.sol";

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument.
            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}

File 7 of 16 : IOldERC721.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.21;

/// @title IOldERC721
/// @notice Interface for the old ERC721 standard.
interface IOldERC721 {
    function balanceOf(address _owner) external view returns (uint256 _balance);

    function ownerOf(uint256 _tokenId) external view returns (address _owner);

    function transfer(address _to, uint256 _tokenId) external;

    function approve(address _to, uint256 _tokenId) external;

    function takeOwnership(uint256 _tokenId) external;

    function tokenURI(
        uint256 _tokenId
    ) external view returns (string memory _uri);
}

File 8 of 16 : IUserVault.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.20;

interface IUserVault {
    /// @notice Mint a new vault to msg.sender
    /// @return newId The id of the new vault
    function mint() external returns (uint256);

    /// @notice Burn a vault and return all assets to owner.
    function burn(uint256 _vaultId, address _assetRecipient) external;

    /// @notice Burn a vault and return all assets to owner.
    /// @param _vaultId The vault to burn.
    /// @param _collections The NFT collections to withdraw.
    /// @param _tokenIds The NFT token IDs to burn.
    /// @param _tokens The ERC20 tokens to withdraw.
    /// @param _collections The ERC1155 collections to withdraw.
    /// @param _tokenIds The ERC1155 token IDs to burn.
    function burnAndWithdraw(
        uint256 _vaultId,
        address[] calldata _collections,
        uint256[] calldata _tokenIds,
        address[] calldata _tokens,
        address[] calldata _erc1155Tokens,
        uint256[] calldata _erc1155TokensIds
    ) external;

    /// @notice Get the vault owner of an NFT. Will return 0 if none.
    /// @param _collection The NFT collection.
    /// @param _tokenId The NFT token ID.
    /// @return vaultId The vault owning the NFT.
    function ERC721OwnerOf(
        address _collection,
        uint256 _tokenId
    ) external view returns (uint256);

    /// @notice Get the balance for a given token for a given vault. address(0) = ETH
    /// @param _vaultId The vault to check.
    /// @param _token The token to check.
    /// @return Balance The balance of the token in the vault.
    function ERC20BalanceOf(
        uint256 _vaultId,
        address _token
    ) external view returns (uint256);

    /// @notice Deposit an NFT into the vault.
    /// @param _vaultId The vault to deposit into.
    /// @param _collection The NFT collection.
    /// @param _tokenId The NFT token ID.
    function depositERC721(
        uint256 _vaultId,
        address _collection,
        uint256 _tokenId
    ) external;

    /// @notice Deposit multiple NFTs.
    /// @param _vaultId The vault to deposit into.
    /// @param _collection The NFT collection.
    /// @param _tokenIds The NFT token IDs.
    function depositERC721s(
        uint256 _vaultId,
        address _collection,
        uint256[] calldata _tokenIds
    ) external;

    /// @notice Deposit an ERC20 token into the vault.
    /// @param _vaultId The vault to deposit into.
    /// @param _token The ERC20 token.
    /// @param _amount The amount to deposit.
    function depositERC20(
        uint256 _vaultId,
        address _token,
        uint256 _amount
    ) external;

    /// @notice Deposit an ERC1155 token into the vault.
    /// @param _vaultId The vault to deposit into.
    /// @param _token The ERC1155 token.
    /// @param _tokenId The ERC1155 token.
    /// @param _amount The amount to deposit.
    function depositERC1155(
        uint256 _vaultId,
        address _token,
        uint256 _tokenId,
        uint256 _amount
    ) external;

    /// @notice Deposit multiple ERC1155 tokens into the vault.
    /// @param _vaultId The vault to deposit into.
    /// @param _token The ERC1155 token.
    /// @param _tokenIds The ERC1155 token.
    /// @param _amounts The amount to deposit.
    function depositERC1155s(
        uint256 _vaultId,
        address _token,
        uint256[] calldata _tokenIds,
        uint256[] calldata _amounts
    ) external;

    /// @notice Deposit ETH into the vault.
    /// @param _vaultId The vault to deposit into.
    function depositEth(uint256 _vaultId) external payable;

    /// @notice Withdraw an NFT from the vault.
    /// @param _vaultId The vault to withdraw from.
    /// @param _collection The NFT collection.
    /// @param _tokenId The NFT token ID.
    function withdrawERC721(
        uint256 _vaultId,
        address _collection,
        uint256 _tokenId
    ) external;

    /// @notice Withdraw multiple NFTs.
    /// @param _vaultId The vault to withdraw from.
    /// @param _collections The NFT collections.
    /// @param _tokenIds The NFT token IDs.
    function withdrawERC721s(
        uint256 _vaultId,
        address[] calldata _collections,
        uint256[] calldata _tokenIds
    ) external;

    /// @notice Withdraw an ERC20 token from the vault.
    /// @param _vaultId The vault to withdraw from.
    /// @param _token The ERC20 token.
    function withdrawERC20(uint256 _vaultId, address _token) external;

    /// @notice Withdraw ERC20s from the vault.
    /// @param _vaultId The vault to withdraw from.
    /// @param _tokens The ERC20 tokens.
    function withdrawERC20s(
        uint256 _vaultId,
        address[] calldata _tokens
    ) external;

    /// @notice Withdraw an ERC20 token from the vault.
    /// @param _vaultId The vault to withdraw from.
    /// @param _token The ERC20 token.
    function withdrawERC1155(
        uint256 _vaultId,
        address _token,
        uint256 _tokenId
    ) external;

    /// @notice Withdraw ERC20s from the vault.
    /// @param _vaultId The vault to withdraw from.
    /// @param _tokens The ERC20 tokens.
    function withdrawERC1155s(
        uint256 _vaultId,
        address[] calldata _tokens,
        uint256[] calldata _tokenIds
    ) external;

    /// @notice Withdraw ETH from the vault.
    /// @param _vaultId The vault to withdraw from.
    function withdrawEth(uint256 _vaultId) external;
}

File 9 of 16 : AddressManager.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.21;

import "@solmate/auth/Owned.sol";
import "@solmate/utils/ReentrancyGuard.sol";

import "./InputChecker.sol";

/// @title AddressManager
/// @notice A contract that handles a whitelist of addresses and their indexes.
/// @dev We assume no more than 65535 addresses will be added to the directory.
contract AddressManager is Owned, ReentrancyGuard {
    using InputChecker for address;

    event AddressAdded(address address_added);

    event AddressRemovedFromWhitelist(address address_removed);

    event AddressWhitelisted(address address_whitelisted);

    error AddressAlreadyAddedError(address _address);

    error AddressNotAddedError(address _address);

    mapping(address => uint16) private _directory;

    mapping(uint16 => address) private _inverseDirectory;

    mapping(address => bool) private _whitelist;

    uint16 private _lastAdded;

    constructor(address[] memory _original) Owned(tx.origin) {
        uint256 total = _original.length;
        for (uint256 i; i < total;) {
            _add(_original[i]);
            unchecked {
                ++i;
            }
        }
    }

    /// @notice Adds an address to the directory. If it already exists,
    ///        reverts. It assumes it's whitelisted.
    /// @param _entry The address to add.
    /// @return The index of the address in the directory.
    function add(address _entry) external payable onlyOwner returns (uint16) {
        return _add(_entry);
    }

    /// @notice Whitelist an address that's already part of the directory.
    /// @param _entry The address to whitelist.
    function addToWhitelist(address _entry) external payable onlyOwner {
        if (_directory[_entry] == 0) {
            revert AddressNotAddedError(_entry);
        }
        _whitelist[_entry] = true;

        emit AddressWhitelisted(_entry);
    }

    /// @notice Removes an address from the whitelist. We still keep it
    ///         in the directory since this mapping is relevant across time.
    /// @param _entry The address to remove from the whitelist.
    function removeFromWhitelist(address _entry) external payable onlyOwner {
        _whitelist[_entry] = false;

        emit AddressRemovedFromWhitelist(_entry);
    }

    /// @param _address The address to get the index for.
    /// @return The index for a given address.
    function addressToIndex(address _address) external view returns (uint16) {
        return _directory[_address];
    }

    /// @param _index The index to get the address for.
    /// @return The address for a given index.
    function indexToAddress(uint16 _index) external view returns (address) {
        return _inverseDirectory[_index];
    }

    /// @param _entry The address to check if it's whitelisted.
    /// @return Whether the address is whitelisted or not.
    function isWhitelisted(address _entry) external view returns (bool) {
        return _whitelist[_entry];
    }

    function _add(address _entry) private returns (uint16) {
        _entry.checkNotZero();
        if (_directory[_entry] != 0) {
            revert AddressAlreadyAddedError(_entry);
        }
        unchecked {
            ++_lastAdded;
        }
        _directory[_entry] = _lastAdded;
        _inverseDirectory[_lastAdded] = _entry;
        _whitelist[_entry] = true;

        emit AddressAdded(_entry);

        return _lastAdded;
    }
}

File 10 of 16 : Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol)

pragma solidity ^0.8.20;

import {Panic} from "../Panic.sol";
import {SafeCast} from "./SafeCast.sol";

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Floor, // Toward negative infinity
        Ceil, // Toward positive infinity
        Trunc, // Toward zero
        Expand // Away from zero
    }

    /**
     * @dev Returns the addition of two unsigned integers, with an success flag (no overflow).
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            uint256 c = a + b;
            if (c < a) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, with an success flag (no overflow).
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            if (b > a) return (false, 0);
            return (true, a - b);
        }
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an success flag (no overflow).
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
            // benefit is lost if 'b' is also tested.
            // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
            if (a == 0) return (true, 0);
            uint256 c = a * b;
            if (c / a != b) return (false, 0);
            return (true, c);
        }
    }

    /**
     * @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a / b);
        }
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
        unchecked {
            if (b == 0) return (false, 0);
            return (true, a % b);
        }
    }

    /**
     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
     *
     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
     * one branch when needed, making this function more expensive.
     */
    function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
        unchecked {
            // branchless ternary works because:
            // b ^ (a ^ b) == a
            // b ^ 0 == b
            return b ^ ((a ^ b) * SafeCast.toUint(condition));
        }
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return ternary(a > b, a, b);
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return ternary(a < b, a, b);
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds towards infinity instead
     * of rounding towards zero.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        if (b == 0) {
            // Guarantee the same behavior as in a regular Solidity division.
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }

        // The following calculation ensures accurate ceiling division without overflow.
        // Since a is non-zero, (a - 1) / b will not overflow.
        // The largest possible result occurs when (a - 1) / b is type(uint256).max,
        // but the largest value we can obtain is type(uint256).max - 1, which happens
        // when a = type(uint256).max and b = 1.
        unchecked {
            return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
        }
    }

    /**
     * @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
     * denominator == 0.
     *
     * Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
     * Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2²⁵⁶ + prod0.
            uint256 prod0 = x * y; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
            if (denominator <= prod1) {
                Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
            }

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator.
            // Always >= 1. See https://cs.stackexchange.com/q/138556/92363.

            uint256 twos = denominator & (0 - denominator);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
            // that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv ≡ 1 mod 2⁴.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
            // works in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
            inverse *= 2 - denominator * inverse; // inverse mod 2³²
            inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
            inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
            inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
            // less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
    }

    /**
     * @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
     *
     * If n is a prime, then Z/nZ is a field. In that case all elements are inversible, expect 0.
     * If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
     *
     * If the input value is not inversible, 0 is returned.
     *
     * NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Ferma's little theorem and get the
     * inverse using `Math.modExp(a, n - 2, n)`.
     */
    function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
        unchecked {
            if (n == 0) return 0;

            // The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
            // Used to compute integers x and y such that: ax + ny = gcd(a, n).
            // When the gcd is 1, then the inverse of a modulo n exists and it's x.
            // ax + ny = 1
            // ax = 1 + (-y)n
            // ax ≡ 1 (mod n) # x is the inverse of a modulo n

            // If the remainder is 0 the gcd is n right away.
            uint256 remainder = a % n;
            uint256 gcd = n;

            // Therefore the initial coefficients are:
            // ax + ny = gcd(a, n) = n
            // 0a + 1n = n
            int256 x = 0;
            int256 y = 1;

            while (remainder != 0) {
                uint256 quotient = gcd / remainder;

                (gcd, remainder) = (
                    // The old remainder is the next gcd to try.
                    remainder,
                    // Compute the next remainder.
                    // Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
                    // where gcd is at most n (capped to type(uint256).max)
                    gcd - remainder * quotient
                );

                (x, y) = (
                    // Increment the coefficient of a.
                    y,
                    // Decrement the coefficient of n.
                    // Can overflow, but the result is casted to uint256 so that the
                    // next value of y is "wrapped around" to a value between 0 and n - 1.
                    x - y * int256(quotient)
                );
            }

            if (gcd != 1) return 0; // No inverse exists.
            return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
        }
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
     *
     * Requirements:
     * - modulus can't be zero
     * - underlying staticcall to precompile must succeed
     *
     * IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
     * sure the chain you're using it on supports the precompiled contract for modular exponentiation
     * at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
     * the underlying function will succeed given the lack of a revert, but the result may be incorrectly
     * interpreted as 0.
     */
    function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
        (bool success, uint256 result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
     * It includes a success flag indicating if the operation succeeded. Operation will be marked has failed if trying
     * to operate modulo 0 or if the underlying precompile reverted.
     *
     * IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
     * you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
     * https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
     * of a revert, but the result may be incorrectly interpreted as 0.
     */
    function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
        if (m == 0) return (false, 0);
        /// @solidity memory-safe-assembly
        assembly {
            let ptr := mload(0x40)
            // | Offset    | Content    | Content (Hex)                                                      |
            // |-----------|------------|--------------------------------------------------------------------|
            // | 0x00:0x1f | size of b  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x20:0x3f | size of e  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x40:0x5f | size of m  | 0x0000000000000000000000000000000000000000000000000000000000000020 |
            // | 0x60:0x7f | value of b | 0x<.............................................................b> |
            // | 0x80:0x9f | value of e | 0x<.............................................................e> |
            // | 0xa0:0xbf | value of m | 0x<.............................................................m> |
            mstore(ptr, 0x20)
            mstore(add(ptr, 0x20), 0x20)
            mstore(add(ptr, 0x40), 0x20)
            mstore(add(ptr, 0x60), b)
            mstore(add(ptr, 0x80), e)
            mstore(add(ptr, 0xa0), m)

            // Given the result < m, it's guaranteed to fit in 32 bytes,
            // so we can use the memory scratch space located at offset 0.
            success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
            result := mload(0x00)
        }
    }

    /**
     * @dev Variant of {modExp} that supports inputs of arbitrary length.
     */
    function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
        (bool success, bytes memory result) = tryModExp(b, e, m);
        if (!success) {
            Panic.panic(Panic.DIVISION_BY_ZERO);
        }
        return result;
    }

    /**
     * @dev Variant of {tryModExp} that supports inputs of arbitrary length.
     */
    function tryModExp(
        bytes memory b,
        bytes memory e,
        bytes memory m
    ) internal view returns (bool success, bytes memory result) {
        if (_zeroBytes(m)) return (false, new bytes(0));

        uint256 mLen = m.length;

        // Encode call args in result and move the free memory pointer
        result = abi.encodePacked(b.length, e.length, mLen, b, e, m);

        /// @solidity memory-safe-assembly
        assembly {
            let dataPtr := add(result, 0x20)
            // Write result on top of args to avoid allocating extra memory.
            success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
            // Overwrite the length.
            // result.length > returndatasize() is guaranteed because returndatasize() == m.length
            mstore(result, mLen)
            // Set the memory pointer after the returned data.
            mstore(0x40, add(dataPtr, mLen))
        }
    }

    /**
     * @dev Returns whether the provided byte array is zero.
     */
    function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
        for (uint256 i = 0; i < byteArray.length; ++i) {
            if (byteArray[i] != 0) {
                return false;
            }
        }
        return true;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
     * towards zero.
     *
     * This method is based on Newton's method for computing square roots; the algorithm is restricted to only
     * using integer operations.
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        unchecked {
            // Take care of easy edge cases when a == 0 or a == 1
            if (a <= 1) {
                return a;
            }

            // In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
            // sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
            // the current value as `ε_n = | x_n - sqrt(a) |`.
            //
            // For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
            // of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
            // bigger than any uint256.
            //
            // By noticing that
            // `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
            // we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
            // to the msb function.
            uint256 aa = a;
            uint256 xn = 1;

            if (aa >= (1 << 128)) {
                aa >>= 128;
                xn <<= 64;
            }
            if (aa >= (1 << 64)) {
                aa >>= 64;
                xn <<= 32;
            }
            if (aa >= (1 << 32)) {
                aa >>= 32;
                xn <<= 16;
            }
            if (aa >= (1 << 16)) {
                aa >>= 16;
                xn <<= 8;
            }
            if (aa >= (1 << 8)) {
                aa >>= 8;
                xn <<= 4;
            }
            if (aa >= (1 << 4)) {
                aa >>= 4;
                xn <<= 2;
            }
            if (aa >= (1 << 2)) {
                xn <<= 1;
            }

            // We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
            //
            // We can refine our estimation by noticing that the middle of that interval minimizes the error.
            // If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
            // This is going to be our x_0 (and ε_0)
            xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)

            // From here, Newton's method give us:
            // x_{n+1} = (x_n + a / x_n) / 2
            //
            // One should note that:
            // x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
            //              = ((x_n² + a) / (2 * x_n))² - a
            //              = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
            //              = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
            //              = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
            //              = (x_n² - a)² / (2 * x_n)²
            //              = ((x_n² - a) / (2 * x_n))²
            //              ≥ 0
            // Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
            //
            // This gives us the proof of quadratic convergence of the sequence:
            // ε_{n+1} = | x_{n+1} - sqrt(a) |
            //         = | (x_n + a / x_n) / 2 - sqrt(a) |
            //         = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
            //         = | (x_n - sqrt(a))² / (2 * x_n) |
            //         = | ε_n² / (2 * x_n) |
            //         = ε_n² / | (2 * x_n) |
            //
            // For the first iteration, we have a special case where x_0 is known:
            // ε_1 = ε_0² / | (2 * x_0) |
            //     ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
            //     ≤ 2**(2*e-4) / (3 * 2**(e-1))
            //     ≤ 2**(e-3) / 3
            //     ≤ 2**(e-3-log2(3))
            //     ≤ 2**(e-4.5)
            //
            // For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
            // ε_{n+1} = ε_n² / | (2 * x_n) |
            //         ≤ (2**(e-k))² / (2 * 2**(e-1))
            //         ≤ 2**(2*e-2*k) / 2**e
            //         ≤ 2**(e-2*k)
            xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5)  -- special case, see above
            xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9)    -- general case with k = 4.5
            xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18)   -- general case with k = 9
            xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36)   -- general case with k = 18
            xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72)   -- general case with k = 36
            xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144)  -- general case with k = 72

            // Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
            // ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
            // sqrt(a) or sqrt(a) + 1.
            return xn - SafeCast.toUint(xn > a / xn);
        }
    }

    /**
     * @dev Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
        }
    }

    /**
     * @dev Return the log in base 2 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        uint256 exp;
        unchecked {
            exp = 128 * SafeCast.toUint(value > (1 << 128) - 1);
            value >>= exp;
            result += exp;

            exp = 64 * SafeCast.toUint(value > (1 << 64) - 1);
            value >>= exp;
            result += exp;

            exp = 32 * SafeCast.toUint(value > (1 << 32) - 1);
            value >>= exp;
            result += exp;

            exp = 16 * SafeCast.toUint(value > (1 << 16) - 1);
            value >>= exp;
            result += exp;

            exp = 8 * SafeCast.toUint(value > (1 << 8) - 1);
            value >>= exp;
            result += exp;

            exp = 4 * SafeCast.toUint(value > (1 << 4) - 1);
            value >>= exp;
            result += exp;

            exp = 2 * SafeCast.toUint(value > (1 << 2) - 1);
            value >>= exp;
            result += exp;

            result += SafeCast.toUint(value > 1);
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
        }
    }

    /**
     * @dev Return the log in base 10 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
        }
    }

    /**
     * @dev Return the log in base 256 of a positive value rounded towards zero.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        uint256 isGt;
        unchecked {
            isGt = SafeCast.toUint(value > (1 << 128) - 1);
            value >>= isGt * 128;
            result += isGt * 16;

            isGt = SafeCast.toUint(value > (1 << 64) - 1);
            value >>= isGt * 64;
            result += isGt * 8;

            isGt = SafeCast.toUint(value > (1 << 32) - 1);
            value >>= isGt * 32;
            result += isGt * 4;

            isGt = SafeCast.toUint(value > (1 << 16) - 1);
            value >>= isGt * 16;
            result += isGt * 2;

            result += SafeCast.toUint(value > (1 << 8) - 1);
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
        }
    }

    /**
     * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
     */
    function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
        return uint8(rounding) % 2 == 1;
    }
}

File 11 of 16 : SignedMath.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)

pragma solidity ^0.8.20;

import {SafeCast} from "./SafeCast.sol";

/**
 * @dev Standard signed math utilities missing in the Solidity language.
 */
library SignedMath {
    /**
     * @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
     *
     * IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
     * However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
     * one branch when needed, making this function more expensive.
     */
    function ternary(bool condition, int256 a, int256 b) internal pure returns (int256) {
        unchecked {
            // branchless ternary works because:
            // b ^ (a ^ b) == a
            // b ^ 0 == b
            return b ^ ((a ^ b) * int256(SafeCast.toUint(condition)));
        }
    }

    /**
     * @dev Returns the largest of two signed numbers.
     */
    function max(int256 a, int256 b) internal pure returns (int256) {
        return ternary(a > b, a, b);
    }

    /**
     * @dev Returns the smallest of two signed numbers.
     */
    function min(int256 a, int256 b) internal pure returns (int256) {
        return ternary(a < b, a, b);
    }

    /**
     * @dev Returns the average of two signed numbers without overflow.
     * The result is rounded towards zero.
     */
    function average(int256 a, int256 b) internal pure returns (int256) {
        // Formula from the book "Hacker's Delight"
        int256 x = (a & b) + ((a ^ b) >> 1);
        return x + (int256(uint256(x) >> 255) & (a ^ b));
    }

    /**
     * @dev Returns the absolute unsigned value of a signed value.
     */
    function abs(int256 n) internal pure returns (uint256) {
        unchecked {
            // Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.
            // Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,
            // taking advantage of the most significant (or "sign" bit) in two's complement representation.
            // This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,
            // the mask will either be `bytes(0)` (if n is positive) or `~bytes32(0)` (if n is negative).
            int256 mask = n >> 255;

            // A `bytes(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.
            return uint256((n + mask) ^ mask);
        }
    }
}

File 12 of 16 : ERC20.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

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

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

File 13 of 16 : ReentrancyGuard.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
    uint256 private locked = 1;

    modifier nonReentrant() virtual {
        require(locked == 1, "REENTRANCY");

        locked = 2;

        _;

        locked = 1;
    }
}

File 14 of 16 : InputChecker.sol
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.21;

/// @title InputChecker
/// @author Florida St
/// @notice Some basic input checks.
library InputChecker {
    error AddressZeroError();

    function checkNotZero(address _address) internal pure {
        if (_address == address(0)) {
            revert AddressZeroError();
        }
    }
}

File 15 of 16 : Panic.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

/**
 * @dev Helper library for emitting standardized panic codes.
 *
 * ```solidity
 * contract Example {
 *      using Panic for uint256;
 *
 *      // Use any of the declared internal constants
 *      function foo() { Panic.GENERIC.panic(); }
 *
 *      // Alternatively
 *      function foo() { Panic.panic(Panic.GENERIC); }
 * }
 * ```
 *
 * Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
 */
// slither-disable-next-line unused-state
library Panic {
    /// @dev generic / unspecified error
    uint256 internal constant GENERIC = 0x00;
    /// @dev used by the assert() builtin
    uint256 internal constant ASSERT = 0x01;
    /// @dev arithmetic underflow or overflow
    uint256 internal constant UNDER_OVERFLOW = 0x11;
    /// @dev division or modulo by zero
    uint256 internal constant DIVISION_BY_ZERO = 0x12;
    /// @dev enum conversion error
    uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
    /// @dev invalid encoding in storage
    uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
    /// @dev empty array pop
    uint256 internal constant EMPTY_ARRAY_POP = 0x31;
    /// @dev array out of bounds access
    uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
    /// @dev resource error (too large allocation or too large array)
    uint256 internal constant RESOURCE_ERROR = 0x41;
    /// @dev calling invalid internal function
    uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;

    /// @dev Reverts with a panic code. Recommended to use with
    /// the internal constants with predefined codes.
    function panic(uint256 code) internal pure {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x4e487b71)
            mstore(0x20, code)
            revert(0x1c, 0x24)
        }
    }
}

File 16 of 16 : SafeCast.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.

pragma solidity ^0.8.20;

/**
 * @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
 * checks.
 *
 * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
 * easily result in undesired exploitation or bugs, since developers usually
 * assume that overflows raise errors. `SafeCast` restores this intuition by
 * reverting the transaction when such an operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeCast {
    /**
     * @dev Value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);

    /**
     * @dev An int value doesn't fit in an uint of `bits` size.
     */
    error SafeCastOverflowedIntToUint(int256 value);

    /**
     * @dev Value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);

    /**
     * @dev An uint value doesn't fit in an int of `bits` size.
     */
    error SafeCastOverflowedUintToInt(uint256 value);

    /**
     * @dev Returns the downcasted uint248 from uint256, reverting on
     * overflow (when the input is greater than largest uint248).
     *
     * Counterpart to Solidity's `uint248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toUint248(uint256 value) internal pure returns (uint248) {
        if (value > type(uint248).max) {
            revert SafeCastOverflowedUintDowncast(248, value);
        }
        return uint248(value);
    }

    /**
     * @dev Returns the downcasted uint240 from uint256, reverting on
     * overflow (when the input is greater than largest uint240).
     *
     * Counterpart to Solidity's `uint240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toUint240(uint256 value) internal pure returns (uint240) {
        if (value > type(uint240).max) {
            revert SafeCastOverflowedUintDowncast(240, value);
        }
        return uint240(value);
    }

    /**
     * @dev Returns the downcasted uint232 from uint256, reverting on
     * overflow (when the input is greater than largest uint232).
     *
     * Counterpart to Solidity's `uint232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toUint232(uint256 value) internal pure returns (uint232) {
        if (value > type(uint232).max) {
            revert SafeCastOverflowedUintDowncast(232, value);
        }
        return uint232(value);
    }

    /**
     * @dev Returns the downcasted uint224 from uint256, reverting on
     * overflow (when the input is greater than largest uint224).
     *
     * Counterpart to Solidity's `uint224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toUint224(uint256 value) internal pure returns (uint224) {
        if (value > type(uint224).max) {
            revert SafeCastOverflowedUintDowncast(224, value);
        }
        return uint224(value);
    }

    /**
     * @dev Returns the downcasted uint216 from uint256, reverting on
     * overflow (when the input is greater than largest uint216).
     *
     * Counterpart to Solidity's `uint216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toUint216(uint256 value) internal pure returns (uint216) {
        if (value > type(uint216).max) {
            revert SafeCastOverflowedUintDowncast(216, value);
        }
        return uint216(value);
    }

    /**
     * @dev Returns the downcasted uint208 from uint256, reverting on
     * overflow (when the input is greater than largest uint208).
     *
     * Counterpart to Solidity's `uint208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toUint208(uint256 value) internal pure returns (uint208) {
        if (value > type(uint208).max) {
            revert SafeCastOverflowedUintDowncast(208, value);
        }
        return uint208(value);
    }

    /**
     * @dev Returns the downcasted uint200 from uint256, reverting on
     * overflow (when the input is greater than largest uint200).
     *
     * Counterpart to Solidity's `uint200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toUint200(uint256 value) internal pure returns (uint200) {
        if (value > type(uint200).max) {
            revert SafeCastOverflowedUintDowncast(200, value);
        }
        return uint200(value);
    }

    /**
     * @dev Returns the downcasted uint192 from uint256, reverting on
     * overflow (when the input is greater than largest uint192).
     *
     * Counterpart to Solidity's `uint192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toUint192(uint256 value) internal pure returns (uint192) {
        if (value > type(uint192).max) {
            revert SafeCastOverflowedUintDowncast(192, value);
        }
        return uint192(value);
    }

    /**
     * @dev Returns the downcasted uint184 from uint256, reverting on
     * overflow (when the input is greater than largest uint184).
     *
     * Counterpart to Solidity's `uint184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toUint184(uint256 value) internal pure returns (uint184) {
        if (value > type(uint184).max) {
            revert SafeCastOverflowedUintDowncast(184, value);
        }
        return uint184(value);
    }

    /**
     * @dev Returns the downcasted uint176 from uint256, reverting on
     * overflow (when the input is greater than largest uint176).
     *
     * Counterpart to Solidity's `uint176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toUint176(uint256 value) internal pure returns (uint176) {
        if (value > type(uint176).max) {
            revert SafeCastOverflowedUintDowncast(176, value);
        }
        return uint176(value);
    }

    /**
     * @dev Returns the downcasted uint168 from uint256, reverting on
     * overflow (when the input is greater than largest uint168).
     *
     * Counterpart to Solidity's `uint168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toUint168(uint256 value) internal pure returns (uint168) {
        if (value > type(uint168).max) {
            revert SafeCastOverflowedUintDowncast(168, value);
        }
        return uint168(value);
    }

    /**
     * @dev Returns the downcasted uint160 from uint256, reverting on
     * overflow (when the input is greater than largest uint160).
     *
     * Counterpart to Solidity's `uint160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toUint160(uint256 value) internal pure returns (uint160) {
        if (value > type(uint160).max) {
            revert SafeCastOverflowedUintDowncast(160, value);
        }
        return uint160(value);
    }

    /**
     * @dev Returns the downcasted uint152 from uint256, reverting on
     * overflow (when the input is greater than largest uint152).
     *
     * Counterpart to Solidity's `uint152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toUint152(uint256 value) internal pure returns (uint152) {
        if (value > type(uint152).max) {
            revert SafeCastOverflowedUintDowncast(152, value);
        }
        return uint152(value);
    }

    /**
     * @dev Returns the downcasted uint144 from uint256, reverting on
     * overflow (when the input is greater than largest uint144).
     *
     * Counterpart to Solidity's `uint144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toUint144(uint256 value) internal pure returns (uint144) {
        if (value > type(uint144).max) {
            revert SafeCastOverflowedUintDowncast(144, value);
        }
        return uint144(value);
    }

    /**
     * @dev Returns the downcasted uint136 from uint256, reverting on
     * overflow (when the input is greater than largest uint136).
     *
     * Counterpart to Solidity's `uint136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toUint136(uint256 value) internal pure returns (uint136) {
        if (value > type(uint136).max) {
            revert SafeCastOverflowedUintDowncast(136, value);
        }
        return uint136(value);
    }

    /**
     * @dev Returns the downcasted uint128 from uint256, reverting on
     * overflow (when the input is greater than largest uint128).
     *
     * Counterpart to Solidity's `uint128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toUint128(uint256 value) internal pure returns (uint128) {
        if (value > type(uint128).max) {
            revert SafeCastOverflowedUintDowncast(128, value);
        }
        return uint128(value);
    }

    /**
     * @dev Returns the downcasted uint120 from uint256, reverting on
     * overflow (when the input is greater than largest uint120).
     *
     * Counterpart to Solidity's `uint120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toUint120(uint256 value) internal pure returns (uint120) {
        if (value > type(uint120).max) {
            revert SafeCastOverflowedUintDowncast(120, value);
        }
        return uint120(value);
    }

    /**
     * @dev Returns the downcasted uint112 from uint256, reverting on
     * overflow (when the input is greater than largest uint112).
     *
     * Counterpart to Solidity's `uint112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toUint112(uint256 value) internal pure returns (uint112) {
        if (value > type(uint112).max) {
            revert SafeCastOverflowedUintDowncast(112, value);
        }
        return uint112(value);
    }

    /**
     * @dev Returns the downcasted uint104 from uint256, reverting on
     * overflow (when the input is greater than largest uint104).
     *
     * Counterpart to Solidity's `uint104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toUint104(uint256 value) internal pure returns (uint104) {
        if (value > type(uint104).max) {
            revert SafeCastOverflowedUintDowncast(104, value);
        }
        return uint104(value);
    }

    /**
     * @dev Returns the downcasted uint96 from uint256, reverting on
     * overflow (when the input is greater than largest uint96).
     *
     * Counterpart to Solidity's `uint96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toUint96(uint256 value) internal pure returns (uint96) {
        if (value > type(uint96).max) {
            revert SafeCastOverflowedUintDowncast(96, value);
        }
        return uint96(value);
    }

    /**
     * @dev Returns the downcasted uint88 from uint256, reverting on
     * overflow (when the input is greater than largest uint88).
     *
     * Counterpart to Solidity's `uint88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toUint88(uint256 value) internal pure returns (uint88) {
        if (value > type(uint88).max) {
            revert SafeCastOverflowedUintDowncast(88, value);
        }
        return uint88(value);
    }

    /**
     * @dev Returns the downcasted uint80 from uint256, reverting on
     * overflow (when the input is greater than largest uint80).
     *
     * Counterpart to Solidity's `uint80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toUint80(uint256 value) internal pure returns (uint80) {
        if (value > type(uint80).max) {
            revert SafeCastOverflowedUintDowncast(80, value);
        }
        return uint80(value);
    }

    /**
     * @dev Returns the downcasted uint72 from uint256, reverting on
     * overflow (when the input is greater than largest uint72).
     *
     * Counterpart to Solidity's `uint72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toUint72(uint256 value) internal pure returns (uint72) {
        if (value > type(uint72).max) {
            revert SafeCastOverflowedUintDowncast(72, value);
        }
        return uint72(value);
    }

    /**
     * @dev Returns the downcasted uint64 from uint256, reverting on
     * overflow (when the input is greater than largest uint64).
     *
     * Counterpart to Solidity's `uint64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toUint64(uint256 value) internal pure returns (uint64) {
        if (value > type(uint64).max) {
            revert SafeCastOverflowedUintDowncast(64, value);
        }
        return uint64(value);
    }

    /**
     * @dev Returns the downcasted uint56 from uint256, reverting on
     * overflow (when the input is greater than largest uint56).
     *
     * Counterpart to Solidity's `uint56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toUint56(uint256 value) internal pure returns (uint56) {
        if (value > type(uint56).max) {
            revert SafeCastOverflowedUintDowncast(56, value);
        }
        return uint56(value);
    }

    /**
     * @dev Returns the downcasted uint48 from uint256, reverting on
     * overflow (when the input is greater than largest uint48).
     *
     * Counterpart to Solidity's `uint48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toUint48(uint256 value) internal pure returns (uint48) {
        if (value > type(uint48).max) {
            revert SafeCastOverflowedUintDowncast(48, value);
        }
        return uint48(value);
    }

    /**
     * @dev Returns the downcasted uint40 from uint256, reverting on
     * overflow (when the input is greater than largest uint40).
     *
     * Counterpart to Solidity's `uint40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toUint40(uint256 value) internal pure returns (uint40) {
        if (value > type(uint40).max) {
            revert SafeCastOverflowedUintDowncast(40, value);
        }
        return uint40(value);
    }

    /**
     * @dev Returns the downcasted uint32 from uint256, reverting on
     * overflow (when the input is greater than largest uint32).
     *
     * Counterpart to Solidity's `uint32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toUint32(uint256 value) internal pure returns (uint32) {
        if (value > type(uint32).max) {
            revert SafeCastOverflowedUintDowncast(32, value);
        }
        return uint32(value);
    }

    /**
     * @dev Returns the downcasted uint24 from uint256, reverting on
     * overflow (when the input is greater than largest uint24).
     *
     * Counterpart to Solidity's `uint24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toUint24(uint256 value) internal pure returns (uint24) {
        if (value > type(uint24).max) {
            revert SafeCastOverflowedUintDowncast(24, value);
        }
        return uint24(value);
    }

    /**
     * @dev Returns the downcasted uint16 from uint256, reverting on
     * overflow (when the input is greater than largest uint16).
     *
     * Counterpart to Solidity's `uint16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toUint16(uint256 value) internal pure returns (uint16) {
        if (value > type(uint16).max) {
            revert SafeCastOverflowedUintDowncast(16, value);
        }
        return uint16(value);
    }

    /**
     * @dev Returns the downcasted uint8 from uint256, reverting on
     * overflow (when the input is greater than largest uint8).
     *
     * Counterpart to Solidity's `uint8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toUint8(uint256 value) internal pure returns (uint8) {
        if (value > type(uint8).max) {
            revert SafeCastOverflowedUintDowncast(8, value);
        }
        return uint8(value);
    }

    /**
     * @dev Converts a signed int256 into an unsigned uint256.
     *
     * Requirements:
     *
     * - input must be greater than or equal to 0.
     */
    function toUint256(int256 value) internal pure returns (uint256) {
        if (value < 0) {
            revert SafeCastOverflowedIntToUint(value);
        }
        return uint256(value);
    }

    /**
     * @dev Returns the downcasted int248 from int256, reverting on
     * overflow (when the input is less than smallest int248 or
     * greater than largest int248).
     *
     * Counterpart to Solidity's `int248` operator.
     *
     * Requirements:
     *
     * - input must fit into 248 bits
     */
    function toInt248(int256 value) internal pure returns (int248 downcasted) {
        downcasted = int248(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(248, value);
        }
    }

    /**
     * @dev Returns the downcasted int240 from int256, reverting on
     * overflow (when the input is less than smallest int240 or
     * greater than largest int240).
     *
     * Counterpart to Solidity's `int240` operator.
     *
     * Requirements:
     *
     * - input must fit into 240 bits
     */
    function toInt240(int256 value) internal pure returns (int240 downcasted) {
        downcasted = int240(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(240, value);
        }
    }

    /**
     * @dev Returns the downcasted int232 from int256, reverting on
     * overflow (when the input is less than smallest int232 or
     * greater than largest int232).
     *
     * Counterpart to Solidity's `int232` operator.
     *
     * Requirements:
     *
     * - input must fit into 232 bits
     */
    function toInt232(int256 value) internal pure returns (int232 downcasted) {
        downcasted = int232(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(232, value);
        }
    }

    /**
     * @dev Returns the downcasted int224 from int256, reverting on
     * overflow (when the input is less than smallest int224 or
     * greater than largest int224).
     *
     * Counterpart to Solidity's `int224` operator.
     *
     * Requirements:
     *
     * - input must fit into 224 bits
     */
    function toInt224(int256 value) internal pure returns (int224 downcasted) {
        downcasted = int224(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(224, value);
        }
    }

    /**
     * @dev Returns the downcasted int216 from int256, reverting on
     * overflow (when the input is less than smallest int216 or
     * greater than largest int216).
     *
     * Counterpart to Solidity's `int216` operator.
     *
     * Requirements:
     *
     * - input must fit into 216 bits
     */
    function toInt216(int256 value) internal pure returns (int216 downcasted) {
        downcasted = int216(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(216, value);
        }
    }

    /**
     * @dev Returns the downcasted int208 from int256, reverting on
     * overflow (when the input is less than smallest int208 or
     * greater than largest int208).
     *
     * Counterpart to Solidity's `int208` operator.
     *
     * Requirements:
     *
     * - input must fit into 208 bits
     */
    function toInt208(int256 value) internal pure returns (int208 downcasted) {
        downcasted = int208(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(208, value);
        }
    }

    /**
     * @dev Returns the downcasted int200 from int256, reverting on
     * overflow (when the input is less than smallest int200 or
     * greater than largest int200).
     *
     * Counterpart to Solidity's `int200` operator.
     *
     * Requirements:
     *
     * - input must fit into 200 bits
     */
    function toInt200(int256 value) internal pure returns (int200 downcasted) {
        downcasted = int200(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(200, value);
        }
    }

    /**
     * @dev Returns the downcasted int192 from int256, reverting on
     * overflow (when the input is less than smallest int192 or
     * greater than largest int192).
     *
     * Counterpart to Solidity's `int192` operator.
     *
     * Requirements:
     *
     * - input must fit into 192 bits
     */
    function toInt192(int256 value) internal pure returns (int192 downcasted) {
        downcasted = int192(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(192, value);
        }
    }

    /**
     * @dev Returns the downcasted int184 from int256, reverting on
     * overflow (when the input is less than smallest int184 or
     * greater than largest int184).
     *
     * Counterpart to Solidity's `int184` operator.
     *
     * Requirements:
     *
     * - input must fit into 184 bits
     */
    function toInt184(int256 value) internal pure returns (int184 downcasted) {
        downcasted = int184(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(184, value);
        }
    }

    /**
     * @dev Returns the downcasted int176 from int256, reverting on
     * overflow (when the input is less than smallest int176 or
     * greater than largest int176).
     *
     * Counterpart to Solidity's `int176` operator.
     *
     * Requirements:
     *
     * - input must fit into 176 bits
     */
    function toInt176(int256 value) internal pure returns (int176 downcasted) {
        downcasted = int176(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(176, value);
        }
    }

    /**
     * @dev Returns the downcasted int168 from int256, reverting on
     * overflow (when the input is less than smallest int168 or
     * greater than largest int168).
     *
     * Counterpart to Solidity's `int168` operator.
     *
     * Requirements:
     *
     * - input must fit into 168 bits
     */
    function toInt168(int256 value) internal pure returns (int168 downcasted) {
        downcasted = int168(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(168, value);
        }
    }

    /**
     * @dev Returns the downcasted int160 from int256, reverting on
     * overflow (when the input is less than smallest int160 or
     * greater than largest int160).
     *
     * Counterpart to Solidity's `int160` operator.
     *
     * Requirements:
     *
     * - input must fit into 160 bits
     */
    function toInt160(int256 value) internal pure returns (int160 downcasted) {
        downcasted = int160(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(160, value);
        }
    }

    /**
     * @dev Returns the downcasted int152 from int256, reverting on
     * overflow (when the input is less than smallest int152 or
     * greater than largest int152).
     *
     * Counterpart to Solidity's `int152` operator.
     *
     * Requirements:
     *
     * - input must fit into 152 bits
     */
    function toInt152(int256 value) internal pure returns (int152 downcasted) {
        downcasted = int152(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(152, value);
        }
    }

    /**
     * @dev Returns the downcasted int144 from int256, reverting on
     * overflow (when the input is less than smallest int144 or
     * greater than largest int144).
     *
     * Counterpart to Solidity's `int144` operator.
     *
     * Requirements:
     *
     * - input must fit into 144 bits
     */
    function toInt144(int256 value) internal pure returns (int144 downcasted) {
        downcasted = int144(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(144, value);
        }
    }

    /**
     * @dev Returns the downcasted int136 from int256, reverting on
     * overflow (when the input is less than smallest int136 or
     * greater than largest int136).
     *
     * Counterpart to Solidity's `int136` operator.
     *
     * Requirements:
     *
     * - input must fit into 136 bits
     */
    function toInt136(int256 value) internal pure returns (int136 downcasted) {
        downcasted = int136(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(136, value);
        }
    }

    /**
     * @dev Returns the downcasted int128 from int256, reverting on
     * overflow (when the input is less than smallest int128 or
     * greater than largest int128).
     *
     * Counterpart to Solidity's `int128` operator.
     *
     * Requirements:
     *
     * - input must fit into 128 bits
     */
    function toInt128(int256 value) internal pure returns (int128 downcasted) {
        downcasted = int128(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(128, value);
        }
    }

    /**
     * @dev Returns the downcasted int120 from int256, reverting on
     * overflow (when the input is less than smallest int120 or
     * greater than largest int120).
     *
     * Counterpart to Solidity's `int120` operator.
     *
     * Requirements:
     *
     * - input must fit into 120 bits
     */
    function toInt120(int256 value) internal pure returns (int120 downcasted) {
        downcasted = int120(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(120, value);
        }
    }

    /**
     * @dev Returns the downcasted int112 from int256, reverting on
     * overflow (when the input is less than smallest int112 or
     * greater than largest int112).
     *
     * Counterpart to Solidity's `int112` operator.
     *
     * Requirements:
     *
     * - input must fit into 112 bits
     */
    function toInt112(int256 value) internal pure returns (int112 downcasted) {
        downcasted = int112(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(112, value);
        }
    }

    /**
     * @dev Returns the downcasted int104 from int256, reverting on
     * overflow (when the input is less than smallest int104 or
     * greater than largest int104).
     *
     * Counterpart to Solidity's `int104` operator.
     *
     * Requirements:
     *
     * - input must fit into 104 bits
     */
    function toInt104(int256 value) internal pure returns (int104 downcasted) {
        downcasted = int104(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(104, value);
        }
    }

    /**
     * @dev Returns the downcasted int96 from int256, reverting on
     * overflow (when the input is less than smallest int96 or
     * greater than largest int96).
     *
     * Counterpart to Solidity's `int96` operator.
     *
     * Requirements:
     *
     * - input must fit into 96 bits
     */
    function toInt96(int256 value) internal pure returns (int96 downcasted) {
        downcasted = int96(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(96, value);
        }
    }

    /**
     * @dev Returns the downcasted int88 from int256, reverting on
     * overflow (when the input is less than smallest int88 or
     * greater than largest int88).
     *
     * Counterpart to Solidity's `int88` operator.
     *
     * Requirements:
     *
     * - input must fit into 88 bits
     */
    function toInt88(int256 value) internal pure returns (int88 downcasted) {
        downcasted = int88(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(88, value);
        }
    }

    /**
     * @dev Returns the downcasted int80 from int256, reverting on
     * overflow (when the input is less than smallest int80 or
     * greater than largest int80).
     *
     * Counterpart to Solidity's `int80` operator.
     *
     * Requirements:
     *
     * - input must fit into 80 bits
     */
    function toInt80(int256 value) internal pure returns (int80 downcasted) {
        downcasted = int80(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(80, value);
        }
    }

    /**
     * @dev Returns the downcasted int72 from int256, reverting on
     * overflow (when the input is less than smallest int72 or
     * greater than largest int72).
     *
     * Counterpart to Solidity's `int72` operator.
     *
     * Requirements:
     *
     * - input must fit into 72 bits
     */
    function toInt72(int256 value) internal pure returns (int72 downcasted) {
        downcasted = int72(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(72, value);
        }
    }

    /**
     * @dev Returns the downcasted int64 from int256, reverting on
     * overflow (when the input is less than smallest int64 or
     * greater than largest int64).
     *
     * Counterpart to Solidity's `int64` operator.
     *
     * Requirements:
     *
     * - input must fit into 64 bits
     */
    function toInt64(int256 value) internal pure returns (int64 downcasted) {
        downcasted = int64(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(64, value);
        }
    }

    /**
     * @dev Returns the downcasted int56 from int256, reverting on
     * overflow (when the input is less than smallest int56 or
     * greater than largest int56).
     *
     * Counterpart to Solidity's `int56` operator.
     *
     * Requirements:
     *
     * - input must fit into 56 bits
     */
    function toInt56(int256 value) internal pure returns (int56 downcasted) {
        downcasted = int56(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(56, value);
        }
    }

    /**
     * @dev Returns the downcasted int48 from int256, reverting on
     * overflow (when the input is less than smallest int48 or
     * greater than largest int48).
     *
     * Counterpart to Solidity's `int48` operator.
     *
     * Requirements:
     *
     * - input must fit into 48 bits
     */
    function toInt48(int256 value) internal pure returns (int48 downcasted) {
        downcasted = int48(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(48, value);
        }
    }

    /**
     * @dev Returns the downcasted int40 from int256, reverting on
     * overflow (when the input is less than smallest int40 or
     * greater than largest int40).
     *
     * Counterpart to Solidity's `int40` operator.
     *
     * Requirements:
     *
     * - input must fit into 40 bits
     */
    function toInt40(int256 value) internal pure returns (int40 downcasted) {
        downcasted = int40(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(40, value);
        }
    }

    /**
     * @dev Returns the downcasted int32 from int256, reverting on
     * overflow (when the input is less than smallest int32 or
     * greater than largest int32).
     *
     * Counterpart to Solidity's `int32` operator.
     *
     * Requirements:
     *
     * - input must fit into 32 bits
     */
    function toInt32(int256 value) internal pure returns (int32 downcasted) {
        downcasted = int32(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(32, value);
        }
    }

    /**
     * @dev Returns the downcasted int24 from int256, reverting on
     * overflow (when the input is less than smallest int24 or
     * greater than largest int24).
     *
     * Counterpart to Solidity's `int24` operator.
     *
     * Requirements:
     *
     * - input must fit into 24 bits
     */
    function toInt24(int256 value) internal pure returns (int24 downcasted) {
        downcasted = int24(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(24, value);
        }
    }

    /**
     * @dev Returns the downcasted int16 from int256, reverting on
     * overflow (when the input is less than smallest int16 or
     * greater than largest int16).
     *
     * Counterpart to Solidity's `int16` operator.
     *
     * Requirements:
     *
     * - input must fit into 16 bits
     */
    function toInt16(int256 value) internal pure returns (int16 downcasted) {
        downcasted = int16(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(16, value);
        }
    }

    /**
     * @dev Returns the downcasted int8 from int256, reverting on
     * overflow (when the input is less than smallest int8 or
     * greater than largest int8).
     *
     * Counterpart to Solidity's `int8` operator.
     *
     * Requirements:
     *
     * - input must fit into 8 bits
     */
    function toInt8(int256 value) internal pure returns (int8 downcasted) {
        downcasted = int8(value);
        if (downcasted != value) {
            revert SafeCastOverflowedIntDowncast(8, value);
        }
    }

    /**
     * @dev Converts an unsigned uint256 into a signed int256.
     *
     * Requirements:
     *
     * - input must be less than or equal to maxInt256.
     */
    function toInt256(uint256 value) internal pure returns (int256) {
        // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
        if (value > uint256(type(int256).max)) {
            revert SafeCastOverflowedUintToInt(value);
        }
        return int256(value);
    }

    /**
     * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
     */
    function toUint(bool b) internal pure returns (uint256 u) {
        /// @solidity memory-safe-assembly
        assembly {
            u := iszero(iszero(b))
        }
    }
}

Settings
{
  "remappings": [
    "@forge-std/=lib/forge-std/src/",
    "@openzeppelin/=lib/openzeppelin-contracts/contracts/",
    "@solady/=lib/solady/src/",
    "@solmate/=lib/solmate/src/",
    "@zora/=lib/v3/contracts/",
    "@chainlink/=lib/chainlink/contracts/src/v0.8/",
    "@delegate/=lib/delegate-registry/src/",
    "@seaport/=lib/seaport/lib/",
    "test/=test/",
    "@const/=src/const/default/",
    "@manifoldxyz/=lib/v3/node_modules/@manifoldxyz/",
    "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
    "@rari-capital/=lib/v3/node_modules/@rari-capital/",
    "@rari-capital/solmate/=lib/seaport/lib/solmate/",
    "chainlink/=lib/chainlink/contracts/",
    "delegate-registry/=lib/delegate-registry/",
    "ds-test/=lib/seaport/lib/ds-test/src/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-std/=lib/forge-std/src/",
    "murky/=lib/delegate-registry/lib/murky/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/",
    "openzeppelin/=lib/delegate-registry/lib/openzeppelin-contracts/contracts/",
    "seaport-core/=lib/seaport/lib/seaport-core/",
    "seaport-sol/=lib/seaport/lib/seaport-sol/",
    "seaport-types/=lib/seaport/lib/seaport-types/",
    "seaport/=lib/seaport/",
    "solady/=lib/solady/src/",
    "solarray/=lib/seaport/lib/solarray/src/",
    "solmate/=lib/solmate/src/",
    "v3/=lib/v3/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 20
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"currencyManager","type":"address"},{"internalType":"address","name":"collectionManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AssetNotOwnedError","type":"error"},{"inputs":[],"name":"CollectionNotWhitelistedError","type":"error"},{"inputs":[],"name":"CurrencyNotWhitelistedError","type":"error"},{"inputs":[],"name":"InvalidCallerError","type":"error"},{"inputs":[],"name":"LengthMismatchError","type":"error"},{"inputs":[{"internalType":"uint256","name":"vaultId","type":"uint256"}],"name":"NotApprovedError","type":"error"},{"inputs":[],"name":"VaultNotExistsError","type":"error"},{"inputs":[],"name":"WithdrawingETHError","type":"error"},{"inputs":[],"name":"WrongMethodError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC1155Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC1155Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Deposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"vaultId","type":"uint256"},{"indexed":false,"internalType":"address","name":"collection","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ERC1155BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"ERC20BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"ERC721OwnerOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ETH","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_assetRecipient","type":"address"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address[]","name":"_collections","type":"address[]"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"address[]","name":"_erc1155Tokens","type":"address[]"},{"internalType":"uint256[]","name":"_erc1155TokensIds","type":"uint256[]"}],"name":"burnAndWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"depositERC1155s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"depositERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"depositERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"depositERC721s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"depositEth","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","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":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"withdrawERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"withdrawERC1155s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"withdrawERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"withdrawERC20s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address","name":"_collection","type":"address"},{"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"withdrawERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"},{"internalType":"address[]","name":"_collections","type":"address[]"},{"internalType":"uint256[]","name":"_tokenIds","type":"uint256[]"}],"name":"withdrawERC721s","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_vaultId","type":"uint256"}],"name":"withdrawEth","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60c034620003a0576001600160401b0390601f90601f19906200283738819003848101841683019190868311848410176200038a578084926040948552833981010312620003a0576200005281620003c5565b93620000626020809301620003c5565b936200006d620003a5565b92601084526f11d3d3911257d554d15497d59055531560821b8185015262000094620003a5565b90600382526223aaab60e91b818301528451958487116200038a576000968754966001978881811c911680156200037f575b858210146200036b5790818784931162000318575b508490878311600114620002b7578a92620002ab575b5050600019600383901b1c191690871b1787555b8251948511620002975785548681811c911680156200028c575b8382101462000278579081858796959493116200021f575b5081938511600114620001ba5750508592620001ae575b5050600019600383901b1c191690821b1790555b6006556001600160a01b039182166080521660a05260405161245c9081620003db823960805181611212015260a051818181610a0501528181610bfb01528181610ca401526110c00152f35b0151905038806200014e565b869593929193168588528388209388905b828210620002055750508411620001eb575b505050811b01905562000162565b015160001960f88460031b161c19169055388080620001dd565b8484015186558897909501949384019390810190620001cb565b9091929394508688528288208580880160051c8201928589106200026e575b9188978a9297969594930160051c01915b8281106200025f57505062000137565b8a81558897508991016200024f565b925081926200023e565b634e487b7160e01b88526022600452602488fd5b90607f16906200011f565b634e487b7160e01b87526041600452602487fd5b015190503880620000f1565b90848a9416918b8052868c20928c5b88828210620003015750508411620002e7575b505050811b01875562000105565b015160001960f88460031b161c19169055388080620002d9565b8385015186558d97909501949384019301620002c6565b909150898052848a208780850160051c82019287861062000361575b918b91869594930160051c01915b82811062000352575050620000db565b8c81558594508b910162000342565b9250819262000334565b634e487b7160e01b8a52602260045260248afd5b90607f1690620000c6565b634e487b7160e01b600052604160045260246000fd5b600080fd5b60408051919082016001600160401b038111838210176200038a57604052565b51906001600160a01b0382168203620003a05756fe6080604052600436101561001257600080fd5b60003560e01c806301b3fab11461025757806301ffc9a71461025257806306fdde031461024d578063081812fc14610248578063095ea7b3146102435780630f4d14e91461023e5780631249c58b14610239578063150b7a02146102345780631b8d7cac1461022f57806323b872dd1461022a5780632440932f1461022557806336fa5e6e1461022057806342842e0e1461021b5780634ec028901461021657806357c8dbbf146102115780635882e1951461020c5780636352211e1461020757806370a08231146102025780638322fff2146101fd57806384437725146101f85780638736e13b146101f357806395d89b41146101ee578063a22cb465146101e9578063a72cefe2146101e4578063a7323f9d146101df578063b0facab3146101da578063b88d4fde146101d5578063bc197c81146101d0578063c20938e0146101cb578063c311d049146101c6578063c87b56dd146101c1578063e985e9c5146101bc578063ede41a90146101b7578063f23a6e61146101b2578063f63b9b38146101ad5763fcd3533c146101a857600080fd5b6117ea565b6117d3565b611779565b611711565b6116b9565b6114c4565b6114a8565b611480565b6113f1565b611316565b6111af565b611156565b611038565b610faf565b610ee4565b610e79565b610dec565b610dbd565b610d3b565b610d0b565b610c6a565b610bb0565b610b99565b610ab5565b61099a565b61094f565b610938565b610866565b610812565b6106d1565b61062c565b610562565b61052e565b610401565b6102cf565b610272565b6001600160a01b0381160361026d57565b600080fd5b3461026d57604036600319011261026d5760043561028f8161025c565b60018060a01b0316600052600860205260406000206024356000526020526020604060002054604051908152f35b6001600160e01b031981160361026d57565b3461026d57602036600319011261026d5760206004356102ee816102bd565b63ffffffff60e01b166301ffc9a760e01b811490811561032c575b811561031b575b506040519015158152f35b635b5e139f60e01b14905038610310565b6380ac58cd60e01b81149150610309565b600091031261026d57565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161037157604052565b610348565b604081019081106001600160401b0382111761037157604052565b90601f801991011681019081106001600160401b0382111761037157604052565b60005b8381106103c55750506000910152565b81810151838201526020016103b5565b604091602082526103f581518092816020860152602086860191016103b2565b601f01601f1916010190565b3461026d5760008060031936011261050857604051908080549060019180831c928082169283156104fe575b60209283861085146104ea5785885260208801949081156104c95750600114610471575b61046d8761046181890382610391565b604051918291826103d5565b0390f35b6000805294509192917f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b8386106104b857505050910190506104618261046d3880610451565b80548587015294820194810161049c565b60ff191685525050505090151560051b0190506104618261046d3880610451565b634e487b7160e01b82526022600452602482fd5b93607f169361042d565b80fd5b6000526004602052604060002090565b6001600160a01b03909116815260200190565b3461026d57602036600319011261026d576004356000526004602052602060018060a01b0360406000205416604051908152f35b3461026d57604036600319011261026d5760043561057f8161025c565b60243560008181526002602052604081205490926001600160a01b0391821691903383148015610608575b6105b390611871565b6105df816105c08661050b565b80546001600160a01b0319166001600160a01b03909216919091179055565b16907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258480a480f35b5082855260056020526105b360ff61062333604089206116a2565b541690506105aa565b602036600319011261026d576004356106448161239d565b60008181527ea206b70d87cacff7a19f3d98e0957b781c25fb4ae954252c87bcf40626174260205260408120805491927f29e8ab3a5ee1054a4bad5627fd68b00e7cb87684fe0d98f8625af41385ff5afe9260609273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee916106ba903490611bba565b90556040519182526020820152346040820152a180f35b3461026d576000806003193601126105085760016006540190816006556106f93315156118ae565b818152600260205260408120546001600160a01b03166107625761071c33611654565b8054600101905561073b336105c0846000526002602052604060002090565b61046d8260405193849333906000805160206124078339815191528180a482526020820190565b60405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606490fd5b9181601f8401121561026d578235916001600160401b03831161026d576020838186019501011161026d57565b90608060031983011261026d576004356107de8161025c565b916024356107eb8161025c565b9160443591606435906001600160401b03821161026d5761080e91600401610798565b9091565b3461026d57610820366107c5565b50505050506020604051630a85bd0160e11b8152f35b9181601f8401121561026d578235916001600160401b03831161026d576020808501948460051b01011161026d57565b3461026d5760c036600319011261026d576001600160401b03600460243582811161026d576108989036908301610836565b60449291923584811161026d576108b29036908401610836565b60649291923586811161026d576108cc9036908601610836565b9160843588811161026d576108e49036908801610836565b95909460a435998a1161026d5761090161090a9a36908a01610836565b99909835611ad8565b005b606090600319011261026d576004356109248161025c565b906024356109318161025c565b9060443590565b3461026d5761090a6109493661090c565b916118ee565b3461026d57604036600319011261026d5760243561096c8161025c565b60018060a01b0316600052600960205260406000206004356000526020526020604060002054604051908152f35b3461026d57606036600319011261026d576004356024356109ba8161025c565b6044356001600160401b03811161026d576109d9903690600401610836565b926109e38161239d565b604051633af32abf60e01b815260208180610a01876004830161051b565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610ab057600091610a82575b5015610a705760005b848110610a5057005b80610a6a610a616001938887611aa8565b35868533611cae565b01610a47565b6040516378d31c7360e11b8152600490fd5b610aa3915060203d8111610aa9575b610a9b8183610391565b810190611ba5565b38610a3e565b503d610a91565b611a5d565b3461026d57610ac33661090c565b91610acf8383836118ee565b813b15918215610ae3575b61090a83611a69565b602091925060a460018060a01b03946000604051968794859382630a85bd0160e11b998a8752336004880152166024860152604485015260806064850152826084850152165af18015610ab05761090a92600091610b4f575b506001600160e01b031916143880610ada565b610b70915060203d8111610b76575b610b688183610391565b810190611a45565b38610b3c565b503d610b5e565b606090600319011261026d57600435906024356109318161025c565b3461026d5761090a610baa36610b7d565b916120b2565b3461026d57608036600319011261026d57600435602435610bd08161025c565b610bd98261239d565b604051633af32abf60e01b815260208180610bf7856004830161051b565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610ab057600091610c4c575b5015610a705761090a91606435916044359133611e34565b610c64915060203d8111610aa957610a9b8183610391565b38610c34565b3461026d57610c7836610b7d565b90610c828361239d565b604051633af32abf60e01b815260208180610ca0856004830161051b565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610ab057600091610ced575b5015610a705761090a9233611cae565b610d05915060203d8111610aa957610a9b8183610391565b38610cdd565b3461026d57602036600319011261026d576020610d2960043561184b565b6040516001600160a01b039091168152f35b3461026d57602036600319011261026d57600435610d588161025c565b6001600160a01b03168015610d8957600052600360205261046d604060002054604051918291829190602083019252565b60405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606490fd5b3461026d57600036600319011261026d57602060405173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8152f35b3461026d5760206040610dfe36610b7d565b6001600160a01b039091166000908152600a85528381209181529084528281209181529083522054604051908152f35b90606060031983011261026d57600435916001600160401b039160243583811161026d5782610e5f91600401610836565b9390939260443591821161026d5761080e91600401610836565b3461026d57610e8736610e2e565b91929390828403610ed25760005b848110610e9e57005b80610ecc610eaf600193888a611aa8565b35610eb98161025c565b610ec4838887611aa8565b3590866120b2565b01610e95565b604051637736a16d60e01b8152600490fd5b3461026d57600080600319360112610508576040519080600190815480831c92808216928315610f9b575b60209283861085146104ea5785885260208801949081156104c95750600114610f425761046d8761046181890382610391565b600160005294509192917fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b838610610f8a57505050910190506104618261046d3880610451565b805485870152948201948101610f6e565b93607f1693610f0f565b8015150361026d57565b3461026d57604036600319011261026d57600435610fcc8161025c565b60243590610fd982610fa5565b336000526005602052610ff08160406000206116a2565b9115159160ff1981541660ff841617905560405191825260018060a01b0316907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b3461026d57608036600319011261026d576024356004356110588261025c565b6001600160401b039160443583811161026d57611079903690600401610836565b92909360643590811161026d57611094903690600401610836565b9261109e8361239d565b604051633af32abf60e01b8152602081806110bc856004830161051b565b03817f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03165afa908115610ab057600091611138575b5015610a705760005b85811061110b57005b8061113261111c600193898b611aa8565b35611128838988611aa8565b3590858833611e34565b01611102565b611150915060203d8111610aa957610a9b8183610391565b386110f9565b3461026d5761116436610e2e565b91929390828403610ed25760005b84811061117b57005b806111a961118c600193888a611aa8565b356111968161025c565b6111a1838887611aa8565b359086611eee565b01611172565b3461026d576111bd36610b7d565b916111c78161239d565b6001600160a01b038281169073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee82146113045760206040518092633af32abf60e01b8252818061120e896004830161051b565b03917f0000000000000000000000000000000000000000000000000000000000000000165afa908115610ab0576000916112e6575b50156112d4578361127c7f29e8ab3a5ee1054a4bad5627fd68b00e7cb87684fe0d98f8625af41385ff5afe956112cf9330903390611d55565b6001600160a01b03841660009081526009602052604090206112b69084600052602052604060002090565b90600052602052604060002090565b6112c1828254611bba565b905560405193849384611bdd565b0390a1005b60405163a212b5d360e01b8152600490fd5b6112fe915060203d8111610aa957610a9b8183610391565b38611243565b604051630130141160e61b8152600490fd5b3461026d57611324366107c5565b939192906113338483856118ee565b813b15938415611347575b61090a85611a69565b602093945090600086939260a460018060a01b0391604051998a978896879386630a85bd0160e11b9d8e8752336004880152166024860152604485015260806064850152816084850152848401378181018301859052601f01601f19168101030193165af18015610ab05761090a926000916113d3575b506001600160e01b031916143880808061133e565b6113eb915060203d8111610b7657610b688183610391565b386113be565b3461026d5760a036600319011261026d5761140d60043561025c565b61141860243561025c565b6001600160401b0360443581811161026d57611438903690600401610836565b505060643581811161026d57611452903690600401610836565b505060843590811161026d5761146c903690600401610798565b505060405163bc197c8160e01b8152602090f35b3461026d57604036600319011261026d5761090a6024356114a08161025c565b600435611fbe565b3461026d57602036600319011261026d5761090a60043561228c565b3461026d57602036600319011261026d576004356040516114e481610376565b601e81527f68747470733a2f2f676f6e64692e78797a2f757365725f7661756c74732f000060208201526000918072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8181811015611646575b506904ee2d6d415b85acef8160201b905080831015611637575b50662386f26fc1000080831015611628575b506305f5e10080831015611619575b506127108083101561160a575b5060648210156115fa575b600a809210156115f0575b6001908160216115a2828801611c5a565b96870101905b6115ba575b61046d6104618787611c19565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a8353049182156115eb579190826115a8565b6115ad565b9260010192611591565b9290606460029104910192611586565b6004919492049101923861157b565b6008919492049101923861156e565b6010919492049101923861155f565b6020919492049101923861154d565b604095500491503880611533565b6001600160a01b0316600090815260036020526040902090565b6001600160a01b0316600090815260086020526040902090565b6001600160a01b03166000908152600a6020526040902090565b9060018060a01b0316600052602052604060002090565b3461026d57604036600319011261026d57602060ff6117056004356116dd8161025c565b602435906116ea8261025c565b6001600160a01b0316600090815260058552604090206116a2565b54166040519015158152f35b3461026d57604036600319011261026d576004356024356001600160401b03811161026d57611744903690600401610836565b919060005b83811061175257005b806117736117636001938786611aa8565b3561176d8161025c565b85611fbe565b01611749565b3461026d5760a036600319011261026d5761179560043561025c565b6117a060243561025c565b6084356001600160401b03811161026d576117bf903690600401610798565b505060405163f23a6e6160e01b8152602090f35b3461026d5761090a6117e436610b7d565b91611eee565b3461026d57604036600319011261026d5761090a60243561180a8161025c565b60043561217a565b1561181957565b60405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606490fd5b6000908152600260205260409020546001600160a01b03169061186f821515611812565b565b1561187857565b60405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606490fd5b156118b557565b60405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606490fd5b9060018060a01b038061190b856000526002602052604060002090565b541691818416928303611a135761194c6119789282169461192d8615156118ae565b84331480156119de575b80156119a9575b61194790611871565b611654565b805460001901905561195d81611654565b805460010190556105c0856000526002602052604060002090565b6119946119848461050b565b80546001600160a01b0319169055565b600080516020612407833981519152600080a4565b506119476119d56119c96119bc8a61050b565b546001600160a01b031690565b6001600160a01b031690565b3314905061193e565b50611a0e611a0733611a028460018060a01b03166000526005602052604060002090565b6116a2565b5460ff1690565b611937565b60405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b6044820152606490fd5b9081602091031261026d5751611a5a816102bd565b90565b6040513d6000823e3d90fd5b15611a7057565b60405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606490fd5b9190811015611ab85760051b0190565b634e487b7160e01b600052603260045260246000fd5b35611a5a8161025c565b999698979593909291611aeb338c61217a565b818103610ed25760005b818110611b7857505050505060005b818110611b585750505060005b818110611b2657505050505061186f9061228c565b80611b52611b3f611b3a600194868a611aa8565b611ace565b611b4a838789611aa8565b3590896120b2565b01611b11565b80611b72611b6c611b3a6001948688611aa8565b8a611fbe565b01611b04565b80611b9f8d611b8d611b3a600195878b611aa8565b611b9884888a611aa8565b3591611eee565b01611af5565b9081602091031261026d5751611a5a81610fa5565b91908201809211611bc757565b634e487b7160e01b600052601160045260246000fd5b9081526001600160a01b039091166020820152604081019190915260600190565b6001600160401b03811161037157601f01601f191660200190565b602061186f919392936040519481611c3a87935180928680870191016103b2565b8201611c4e825180938680850191016103b2565b01038085520183610391565b90611c6482611bfe565b611c716040519182610391565b8281528092611c82601f1991611bfe565b0190602036910137565b6001600160a01b03918216815291166020820152604081019190915260600190565b926001600160a01b038316803b1561026d5781600091611ce796836040518099819582946323b872dd60e01b8452309060048501611c8c565b03925af1908115610ab0577f4e92356bc3e014711be5e60ba880885e904c8baded8441e59854b2cf1f89f8b094611d4192611d46575b50611d278461166e565b816000526020528260406000205560405193849384611bdd565b0390a1565b611d4f9061035e565b38611d1d565b9160008093602095606494604051946323b872dd60e01b865260018060a01b03809216600487015216602485015260448401525af13d15601f3d1160016000511416171615611da057565b60405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606490fd5b929060c0949260018060a01b0380921685521660208401526040830152606082015260a06080820152600060a08201520190565b909493926060926080830196835260018060a01b0316602083015260408201520152565b919290916001600160a01b03841691823b1561026d5780869260405194858092637921219560e11b825281611e7460009c8d978894309060048601611ddc565b03925af18015610ab0577f591c45c6cd9259632b4e9a5cfa0dd0a5ad5dd72470c757c25c184309f44d9da396611d4194604092611edf575b50611eb687611688565b83825260205281812086825260205220611ed1838254611bba565b905560405194859485611e10565b611ee89061035e565b38611eac565b611ef7816123cd565b80611f05846112a78561166e565b5403611fac576001600160a01b03821692833b1561026d57600060405180956323b872dd60e01b8252818381611f4087333060048501611c8c565b03925af1908115610ab0577f20289891ea20aca7d12a5b330123469398894b00725c9e8564c7981114abdc0f94611d4192611f93575b506000611f86826112a78761166e565b5560405193849384611bdd565b80611fa0611fa69261035e565b8061033d565b38611f76565b6040516349e11b0360e01b8152600490fd5b9190611fc9836123cd565b6001600160a01b038116600081815260096020908152604080832087845282528083205490969390929083156120a8578160448285938352600984528a83208884528452828b812055828b519163a9059cbb60e01b83523360048401528860248401525af19051600114601f3d11163d151716156120735750611d41907f893699b7a610f8ef1d97bd0dcc4cc672bc257f1b1ddd063cf2e218153eaf0a8a94955193849384611bdd565b60649086519062461bcd60e51b82526004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152fd5b5050505050509050565b6120bb816123cd565b6120cc816112a7856112a786611688565b549283156121745760006120e7836112a7846112a788611688565b556001600160a01b03831693843b1561026d5760006040518096637921219560e11b825281838161211e8789333060048601611ddc565b03925af1918215610ab0577fabe6b5b858802d850f86c44c35989762d5c479134363a0d7a57c5ef51789ec3095611d4193612161575b5060405194859485611e10565b80611fa061216e9261035e565b38612154565b50505050565b91906001600160a01b038061218e8561184b565b1633141580612260575b8061224b575b612232578361186f93946105c09260009082825260026020526040822054166121c8811515611812565b80825260036020526040822060001981540190556121f0836000526002602052604060002090565b80546001600160a01b031990811690915561220a8461050b565b9081541690556000805160206124078339815191528280a46000526007602052604060002090565b604051633f7d787960e11b815260048101859052602490fd5b5033816122578661050b565b5416141561219e565b508061226b8561184b565b16600052600560205260ff6122843360406000206116a2565b541615612198565b90612296826123cd565b60008281527ea206b70d87cacff7a19f3d98e0957b781c25fb4ae954252c87bcf4062617426020526040808220549093909173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8315612395578152600960205284812082825260205280858120558080808086335af1903d1561238f573d9061231282611bfe565b9161231f88519384610391565b825260203d92013e5b1561237e57925192835273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60208401526040830152907f893699b7a610f8ef1d97bd0dcc4cc672bc257f1b1ddd063cf2e218153eaf0a8a908060608101611d41565b835163439e708560e11b8152600490fd5b50612328565b505050509050565b6000908152600260205260409020546001600160a01b0316156123bc57565b63be7238f360e01b60005260046000fd5b6000818152600760205260409020546001600160a01b031633036123ee5750565b60249060405190633f7d787960e11b82526004820152fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212202bf1d4303a974a9c365b5d1e50143197a6e985423861903be649efb0c9359bcd64736f6c634300081500330000000000000000000000004150ded32a6d3bfecae76e7558af48019034492700000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d7398

Deployed Bytecode

0x6080604052600436101561001257600080fd5b60003560e01c806301b3fab11461025757806301ffc9a71461025257806306fdde031461024d578063081812fc14610248578063095ea7b3146102435780630f4d14e91461023e5780631249c58b14610239578063150b7a02146102345780631b8d7cac1461022f57806323b872dd1461022a5780632440932f1461022557806336fa5e6e1461022057806342842e0e1461021b5780634ec028901461021657806357c8dbbf146102115780635882e1951461020c5780636352211e1461020757806370a08231146102025780638322fff2146101fd57806384437725146101f85780638736e13b146101f357806395d89b41146101ee578063a22cb465146101e9578063a72cefe2146101e4578063a7323f9d146101df578063b0facab3146101da578063b88d4fde146101d5578063bc197c81146101d0578063c20938e0146101cb578063c311d049146101c6578063c87b56dd146101c1578063e985e9c5146101bc578063ede41a90146101b7578063f23a6e61146101b2578063f63b9b38146101ad5763fcd3533c146101a857600080fd5b6117ea565b6117d3565b611779565b611711565b6116b9565b6114c4565b6114a8565b611480565b6113f1565b611316565b6111af565b611156565b611038565b610faf565b610ee4565b610e79565b610dec565b610dbd565b610d3b565b610d0b565b610c6a565b610bb0565b610b99565b610ab5565b61099a565b61094f565b610938565b610866565b610812565b6106d1565b61062c565b610562565b61052e565b610401565b6102cf565b610272565b6001600160a01b0381160361026d57565b600080fd5b3461026d57604036600319011261026d5760043561028f8161025c565b60018060a01b0316600052600860205260406000206024356000526020526020604060002054604051908152f35b6001600160e01b031981160361026d57565b3461026d57602036600319011261026d5760206004356102ee816102bd565b63ffffffff60e01b166301ffc9a760e01b811490811561032c575b811561031b575b506040519015158152f35b635b5e139f60e01b14905038610310565b6380ac58cd60e01b81149150610309565b600091031261026d57565b634e487b7160e01b600052604160045260246000fd5b6001600160401b03811161037157604052565b610348565b604081019081106001600160401b0382111761037157604052565b90601f801991011681019081106001600160401b0382111761037157604052565b60005b8381106103c55750506000910152565b81810151838201526020016103b5565b604091602082526103f581518092816020860152602086860191016103b2565b601f01601f1916010190565b3461026d5760008060031936011261050857604051908080549060019180831c928082169283156104fe575b60209283861085146104ea5785885260208801949081156104c95750600114610471575b61046d8761046181890382610391565b604051918291826103d5565b0390f35b6000805294509192917f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b8386106104b857505050910190506104618261046d3880610451565b80548587015294820194810161049c565b60ff191685525050505090151560051b0190506104618261046d3880610451565b634e487b7160e01b82526022600452602482fd5b93607f169361042d565b80fd5b6000526004602052604060002090565b6001600160a01b03909116815260200190565b3461026d57602036600319011261026d576004356000526004602052602060018060a01b0360406000205416604051908152f35b3461026d57604036600319011261026d5760043561057f8161025c565b60243560008181526002602052604081205490926001600160a01b0391821691903383148015610608575b6105b390611871565b6105df816105c08661050b565b80546001600160a01b0319166001600160a01b03909216919091179055565b16907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258480a480f35b5082855260056020526105b360ff61062333604089206116a2565b541690506105aa565b602036600319011261026d576004356106448161239d565b60008181527ea206b70d87cacff7a19f3d98e0957b781c25fb4ae954252c87bcf40626174260205260408120805491927f29e8ab3a5ee1054a4bad5627fd68b00e7cb87684fe0d98f8625af41385ff5afe9260609273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee916106ba903490611bba565b90556040519182526020820152346040820152a180f35b3461026d576000806003193601126105085760016006540190816006556106f93315156118ae565b818152600260205260408120546001600160a01b03166107625761071c33611654565b8054600101905561073b336105c0846000526002602052604060002090565b61046d8260405193849333906000805160206124078339815191528180a482526020820190565b60405162461bcd60e51b815260206004820152600e60248201526d1053149150511657d3525395115160921b6044820152606490fd5b9181601f8401121561026d578235916001600160401b03831161026d576020838186019501011161026d57565b90608060031983011261026d576004356107de8161025c565b916024356107eb8161025c565b9160443591606435906001600160401b03821161026d5761080e91600401610798565b9091565b3461026d57610820366107c5565b50505050506020604051630a85bd0160e11b8152f35b9181601f8401121561026d578235916001600160401b03831161026d576020808501948460051b01011161026d57565b3461026d5760c036600319011261026d576001600160401b03600460243582811161026d576108989036908301610836565b60449291923584811161026d576108b29036908401610836565b60649291923586811161026d576108cc9036908601610836565b9160843588811161026d576108e49036908801610836565b95909460a435998a1161026d5761090161090a9a36908a01610836565b99909835611ad8565b005b606090600319011261026d576004356109248161025c565b906024356109318161025c565b9060443590565b3461026d5761090a6109493661090c565b916118ee565b3461026d57604036600319011261026d5760243561096c8161025c565b60018060a01b0316600052600960205260406000206004356000526020526020604060002054604051908152f35b3461026d57606036600319011261026d576004356024356109ba8161025c565b6044356001600160401b03811161026d576109d9903690600401610836565b926109e38161239d565b604051633af32abf60e01b815260208180610a01876004830161051b565b03817f00000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d73986001600160a01b03165afa908115610ab057600091610a82575b5015610a705760005b848110610a5057005b80610a6a610a616001938887611aa8565b35868533611cae565b01610a47565b6040516378d31c7360e11b8152600490fd5b610aa3915060203d8111610aa9575b610a9b8183610391565b810190611ba5565b38610a3e565b503d610a91565b611a5d565b3461026d57610ac33661090c565b91610acf8383836118ee565b813b15918215610ae3575b61090a83611a69565b602091925060a460018060a01b03946000604051968794859382630a85bd0160e11b998a8752336004880152166024860152604485015260806064850152826084850152165af18015610ab05761090a92600091610b4f575b506001600160e01b031916143880610ada565b610b70915060203d8111610b76575b610b688183610391565b810190611a45565b38610b3c565b503d610b5e565b606090600319011261026d57600435906024356109318161025c565b3461026d5761090a610baa36610b7d565b916120b2565b3461026d57608036600319011261026d57600435602435610bd08161025c565b610bd98261239d565b604051633af32abf60e01b815260208180610bf7856004830161051b565b03817f00000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d73986001600160a01b03165afa908115610ab057600091610c4c575b5015610a705761090a91606435916044359133611e34565b610c64915060203d8111610aa957610a9b8183610391565b38610c34565b3461026d57610c7836610b7d565b90610c828361239d565b604051633af32abf60e01b815260208180610ca0856004830161051b565b03817f00000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d73986001600160a01b03165afa908115610ab057600091610ced575b5015610a705761090a9233611cae565b610d05915060203d8111610aa957610a9b8183610391565b38610cdd565b3461026d57602036600319011261026d576020610d2960043561184b565b6040516001600160a01b039091168152f35b3461026d57602036600319011261026d57600435610d588161025c565b6001600160a01b03168015610d8957600052600360205261046d604060002054604051918291829190602083019252565b60405162461bcd60e51b815260206004820152600c60248201526b5a45524f5f4144445245535360a01b6044820152606490fd5b3461026d57600036600319011261026d57602060405173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8152f35b3461026d5760206040610dfe36610b7d565b6001600160a01b039091166000908152600a85528381209181529084528281209181529083522054604051908152f35b90606060031983011261026d57600435916001600160401b039160243583811161026d5782610e5f91600401610836565b9390939260443591821161026d5761080e91600401610836565b3461026d57610e8736610e2e565b91929390828403610ed25760005b848110610e9e57005b80610ecc610eaf600193888a611aa8565b35610eb98161025c565b610ec4838887611aa8565b3590866120b2565b01610e95565b604051637736a16d60e01b8152600490fd5b3461026d57600080600319360112610508576040519080600190815480831c92808216928315610f9b575b60209283861085146104ea5785885260208801949081156104c95750600114610f425761046d8761046181890382610391565b600160005294509192917fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b838610610f8a57505050910190506104618261046d3880610451565b805485870152948201948101610f6e565b93607f1693610f0f565b8015150361026d57565b3461026d57604036600319011261026d57600435610fcc8161025c565b60243590610fd982610fa5565b336000526005602052610ff08160406000206116a2565b9115159160ff1981541660ff841617905560405191825260018060a01b0316907f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c3160203392a3005b3461026d57608036600319011261026d576024356004356110588261025c565b6001600160401b039160443583811161026d57611079903690600401610836565b92909360643590811161026d57611094903690600401610836565b9261109e8361239d565b604051633af32abf60e01b8152602081806110bc856004830161051b565b03817f00000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d73986001600160a01b03165afa908115610ab057600091611138575b5015610a705760005b85811061110b57005b8061113261111c600193898b611aa8565b35611128838988611aa8565b3590858833611e34565b01611102565b611150915060203d8111610aa957610a9b8183610391565b386110f9565b3461026d5761116436610e2e565b91929390828403610ed25760005b84811061117b57005b806111a961118c600193888a611aa8565b356111968161025c565b6111a1838887611aa8565b359086611eee565b01611172565b3461026d576111bd36610b7d565b916111c78161239d565b6001600160a01b038281169073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee82146113045760206040518092633af32abf60e01b8252818061120e896004830161051b565b03917f0000000000000000000000004150ded32a6d3bfecae76e7558af480190344927165afa908115610ab0576000916112e6575b50156112d4578361127c7f29e8ab3a5ee1054a4bad5627fd68b00e7cb87684fe0d98f8625af41385ff5afe956112cf9330903390611d55565b6001600160a01b03841660009081526009602052604090206112b69084600052602052604060002090565b90600052602052604060002090565b6112c1828254611bba565b905560405193849384611bdd565b0390a1005b60405163a212b5d360e01b8152600490fd5b6112fe915060203d8111610aa957610a9b8183610391565b38611243565b604051630130141160e61b8152600490fd5b3461026d57611324366107c5565b939192906113338483856118ee565b813b15938415611347575b61090a85611a69565b602093945090600086939260a460018060a01b0391604051998a978896879386630a85bd0160e11b9d8e8752336004880152166024860152604485015260806064850152816084850152848401378181018301859052601f01601f19168101030193165af18015610ab05761090a926000916113d3575b506001600160e01b031916143880808061133e565b6113eb915060203d8111610b7657610b688183610391565b386113be565b3461026d5760a036600319011261026d5761140d60043561025c565b61141860243561025c565b6001600160401b0360443581811161026d57611438903690600401610836565b505060643581811161026d57611452903690600401610836565b505060843590811161026d5761146c903690600401610798565b505060405163bc197c8160e01b8152602090f35b3461026d57604036600319011261026d5761090a6024356114a08161025c565b600435611fbe565b3461026d57602036600319011261026d5761090a60043561228c565b3461026d57602036600319011261026d576004356040516114e481610376565b601e81527f68747470733a2f2f676f6e64692e78797a2f757365725f7661756c74732f000060208201526000918072184f03e93ff9f4daa797ed6e38ed64bf6a1f0160401b8181811015611646575b506904ee2d6d415b85acef8160201b905080831015611637575b50662386f26fc1000080831015611628575b506305f5e10080831015611619575b506127108083101561160a575b5060648210156115fa575b600a809210156115f0575b6001908160216115a2828801611c5a565b96870101905b6115ba575b61046d6104618787611c19565b600019019083906f181899199a1a9b1b9c1cb0b131b232b360811b8282061a8353049182156115eb579190826115a8565b6115ad565b9260010192611591565b9290606460029104910192611586565b6004919492049101923861157b565b6008919492049101923861156e565b6010919492049101923861155f565b6020919492049101923861154d565b604095500491503880611533565b6001600160a01b0316600090815260036020526040902090565b6001600160a01b0316600090815260086020526040902090565b6001600160a01b03166000908152600a6020526040902090565b9060018060a01b0316600052602052604060002090565b3461026d57604036600319011261026d57602060ff6117056004356116dd8161025c565b602435906116ea8261025c565b6001600160a01b0316600090815260058552604090206116a2565b54166040519015158152f35b3461026d57604036600319011261026d576004356024356001600160401b03811161026d57611744903690600401610836565b919060005b83811061175257005b806117736117636001938786611aa8565b3561176d8161025c565b85611fbe565b01611749565b3461026d5760a036600319011261026d5761179560043561025c565b6117a060243561025c565b6084356001600160401b03811161026d576117bf903690600401610798565b505060405163f23a6e6160e01b8152602090f35b3461026d5761090a6117e436610b7d565b91611eee565b3461026d57604036600319011261026d5761090a60243561180a8161025c565b60043561217a565b1561181957565b60405162461bcd60e51b815260206004820152600a6024820152691393d517d3525395115160b21b6044820152606490fd5b6000908152600260205260409020546001600160a01b03169061186f821515611812565b565b1561187857565b60405162461bcd60e51b815260206004820152600e60248201526d1393d517d055551213d49256915160921b6044820152606490fd5b156118b557565b60405162461bcd60e51b81526020600482015260116024820152701253959053125117d49150d25412515395607a1b6044820152606490fd5b9060018060a01b038061190b856000526002602052604060002090565b541691818416928303611a135761194c6119789282169461192d8615156118ae565b84331480156119de575b80156119a9575b61194790611871565b611654565b805460001901905561195d81611654565b805460010190556105c0856000526002602052604060002090565b6119946119848461050b565b80546001600160a01b0319169055565b600080516020612407833981519152600080a4565b506119476119d56119c96119bc8a61050b565b546001600160a01b031690565b6001600160a01b031690565b3314905061193e565b50611a0e611a0733611a028460018060a01b03166000526005602052604060002090565b6116a2565b5460ff1690565b611937565b60405162461bcd60e51b815260206004820152600a60248201526957524f4e475f46524f4d60b01b6044820152606490fd5b9081602091031261026d5751611a5a816102bd565b90565b6040513d6000823e3d90fd5b15611a7057565b60405162461bcd60e51b815260206004820152601060248201526f155394d0519157d49150d2541251539560821b6044820152606490fd5b9190811015611ab85760051b0190565b634e487b7160e01b600052603260045260246000fd5b35611a5a8161025c565b999698979593909291611aeb338c61217a565b818103610ed25760005b818110611b7857505050505060005b818110611b585750505060005b818110611b2657505050505061186f9061228c565b80611b52611b3f611b3a600194868a611aa8565b611ace565b611b4a838789611aa8565b3590896120b2565b01611b11565b80611b72611b6c611b3a6001948688611aa8565b8a611fbe565b01611b04565b80611b9f8d611b8d611b3a600195878b611aa8565b611b9884888a611aa8565b3591611eee565b01611af5565b9081602091031261026d5751611a5a81610fa5565b91908201809211611bc757565b634e487b7160e01b600052601160045260246000fd5b9081526001600160a01b039091166020820152604081019190915260600190565b6001600160401b03811161037157601f01601f191660200190565b602061186f919392936040519481611c3a87935180928680870191016103b2565b8201611c4e825180938680850191016103b2565b01038085520183610391565b90611c6482611bfe565b611c716040519182610391565b8281528092611c82601f1991611bfe565b0190602036910137565b6001600160a01b03918216815291166020820152604081019190915260600190565b926001600160a01b038316803b1561026d5781600091611ce796836040518099819582946323b872dd60e01b8452309060048501611c8c565b03925af1908115610ab0577f4e92356bc3e014711be5e60ba880885e904c8baded8441e59854b2cf1f89f8b094611d4192611d46575b50611d278461166e565b816000526020528260406000205560405193849384611bdd565b0390a1565b611d4f9061035e565b38611d1d565b9160008093602095606494604051946323b872dd60e01b865260018060a01b03809216600487015216602485015260448401525af13d15601f3d1160016000511416171615611da057565b60405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b6044820152606490fd5b929060c0949260018060a01b0380921685521660208401526040830152606082015260a06080820152600060a08201520190565b909493926060926080830196835260018060a01b0316602083015260408201520152565b919290916001600160a01b03841691823b1561026d5780869260405194858092637921219560e11b825281611e7460009c8d978894309060048601611ddc565b03925af18015610ab0577f591c45c6cd9259632b4e9a5cfa0dd0a5ad5dd72470c757c25c184309f44d9da396611d4194604092611edf575b50611eb687611688565b83825260205281812086825260205220611ed1838254611bba565b905560405194859485611e10565b611ee89061035e565b38611eac565b611ef7816123cd565b80611f05846112a78561166e565b5403611fac576001600160a01b03821692833b1561026d57600060405180956323b872dd60e01b8252818381611f4087333060048501611c8c565b03925af1908115610ab0577f20289891ea20aca7d12a5b330123469398894b00725c9e8564c7981114abdc0f94611d4192611f93575b506000611f86826112a78761166e565b5560405193849384611bdd565b80611fa0611fa69261035e565b8061033d565b38611f76565b6040516349e11b0360e01b8152600490fd5b9190611fc9836123cd565b6001600160a01b038116600081815260096020908152604080832087845282528083205490969390929083156120a8578160448285938352600984528a83208884528452828b812055828b519163a9059cbb60e01b83523360048401528860248401525af19051600114601f3d11163d151716156120735750611d41907f893699b7a610f8ef1d97bd0dcc4cc672bc257f1b1ddd063cf2e218153eaf0a8a94955193849384611bdd565b60649086519062461bcd60e51b82526004820152600f60248201526e1514905394d1915497d19052531151608a1b6044820152fd5b5050505050509050565b6120bb816123cd565b6120cc816112a7856112a786611688565b549283156121745760006120e7836112a7846112a788611688565b556001600160a01b03831693843b1561026d5760006040518096637921219560e11b825281838161211e8789333060048601611ddc565b03925af1918215610ab0577fabe6b5b858802d850f86c44c35989762d5c479134363a0d7a57c5ef51789ec3095611d4193612161575b5060405194859485611e10565b80611fa061216e9261035e565b38612154565b50505050565b91906001600160a01b038061218e8561184b565b1633141580612260575b8061224b575b612232578361186f93946105c09260009082825260026020526040822054166121c8811515611812565b80825260036020526040822060001981540190556121f0836000526002602052604060002090565b80546001600160a01b031990811690915561220a8461050b565b9081541690556000805160206124078339815191528280a46000526007602052604060002090565b604051633f7d787960e11b815260048101859052602490fd5b5033816122578661050b565b5416141561219e565b508061226b8561184b565b16600052600560205260ff6122843360406000206116a2565b541615612198565b90612296826123cd565b60008281527ea206b70d87cacff7a19f3d98e0957b781c25fb4ae954252c87bcf4062617426020526040808220549093909173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8315612395578152600960205284812082825260205280858120558080808086335af1903d1561238f573d9061231282611bfe565b9161231f88519384610391565b825260203d92013e5b1561237e57925192835273eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60208401526040830152907f893699b7a610f8ef1d97bd0dcc4cc672bc257f1b1ddd063cf2e218153eaf0a8a908060608101611d41565b835163439e708560e11b8152600490fd5b50612328565b505050509050565b6000908152600260205260409020546001600160a01b0316156123bc57565b63be7238f360e01b60005260046000fd5b6000818152600760205260409020546001600160a01b031633036123ee5750565b60249060405190633f7d787960e11b82526004820152fdfeddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa26469706673582212202bf1d4303a974a9c365b5d1e50143197a6e985423861903be649efb0c9359bcd64736f6c63430008150033

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

0000000000000000000000004150ded32a6d3bfecae76e7558af48019034492700000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d7398

-----Decoded View---------------
Arg [0] : currencyManager (address): 0x4150deD32A6D3bfecAE76e7558Af480190344927
Arg [1] : collectionManager (address): 0x52Ac424eF7B283aA5bADB8c6254832E3280d7398

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000004150ded32a6d3bfecae76e7558af480190344927
Arg [1] : 00000000000000000000000052ac424ef7b283aa5badb8c6254832e3280d7398


Deployed Bytecode Sourcemap

658:14361:15:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;;;:::o;:::-;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;658:14361:15;4891:13;658:14361;;;-1:-1:-1;658:14361:15;;;-1:-1:-1;658:14361:15;;;;;-1:-1:-1;658:14361:15;;;;;;;;;-1:-1:-1;;;;;;658:14361:15;;;;;:::o;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;;:::i;:::-;;;;;;;;4825:25:8;;:100;;;;;658:14361:15;4825:175:8;;;;658:14361:15;;;;;;;;;;4825:175:8;-1:-1:-1;;;4975:25:8;;-1:-1:-1;4825:175:8;;;:100;-1:-1:-1;;;4900:25:8;;;-1:-1:-1;4825:100:8;;658:14361:15;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;:::o;:::-;;:::i;:::-;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;:::o;:::-;;;;;;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;:::o;:::-;;;;;;;;-1:-1:-1;;658:14361:15;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;658:14361:15;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;658:14361:15;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;-1:-1:-1;;;;658:14361:15;;;;;;;-1:-1:-1;658:14361:15;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;-1:-1:-1;658:14361:15;;;;;;;;;;;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;;;-1:-1:-1;658:14361:15;;;2540:8:8;658:14361:15;;;;;;-1:-1:-1;;;;;;;658:14361:15;;;;;2571:10:8;:19;;:58;;;;658:14361:15;2563:85:8;;;:::i;:::-;2659:25;:15;;;;:::i;:::-;658:14361:15;;-1:-1:-1;;;;;;658:14361:15;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;2659:25:8;658:14361:15;2700:28:8;;;;;658:14361:15;;2571:58:8;658:14361:15;;;;2594:16:8;658:14361:15;;2563:85:8;658:14361:15;2594:35:8;2571:10;658:14361:15;;;2594:35:8;:::i;:::-;658:14361:15;;2571:58:8;;;;658:14361:15;;;-1:-1:-1;;658:14361:15;;;;;;8036:8;;;:::i;:::-;-1:-1:-1;658:14361:15;;;;;;;;;;;-1:-1:-1;;8112:40:15;;658:14361;;956:42;;8056:40;;8087:9;;8056:40;:::i;:::-;658:14361;;;;;;;;;;;8087:9;658:14361;;;;8112:40;658:14361;;;;;;;;;;;;;;;;3288:9;658:14361;;;;3288:9;658:14361;5309:46:8;3323:10:15;5317:16:8;;5309:46;:::i;:::-;658:14361:15;;;5374:8:8;658:14361:15;;;;;;-1:-1:-1;;;;;658:14361:15;;;5509:14:8;3323:10:15;5509:14:8;:::i;:::-;658:14361:15;;;;;;5546:17:8;3323:10:15;5546:12:8;;658:14361:15;;5374:8:8;658:14361:15;;;;;;;5546:17:8;658:14361:15;;;;3323:10;;;;5579:28:8;-1:-1:-1;;;;;;;;;;;5579:28:8;;;658:14361:15;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;658:14361:15;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;:::i;:::-;;;:::o;:::-;;;;;;;:::i;:::-;;;;;;;;;7310:45:8;;;658:14361:15;;;;;;;;;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;:::i;:::-;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;:::o;:::-;;;;;;;;:::i;:::-;;;:::i;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;;;;;;;-1:-1:-1;658:14361:15;5069:12;658:14361;;;-1:-1:-1;658:14361:15;;;-1:-1:-1;658:14361:15;;;;;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;:::i;:::-;5934:8;;;;:::i;:::-;658:14361;;-1:-1:-1;;;5958:45:15;;658:14361;;;5958:45;;658:14361;5958:45;;;:::i;:::-;;658:14361;5958:18;-1:-1:-1;;;;;658:14361:15;5958:45;;;;;;;-1:-1:-1;5958:45:15;;;658:14361;5957:46;;5953:115;;-1:-1:-1;6145:15:15;;;;;;658:14361;6130:13;6228:12;;;658:14361;6228:12;;;;:::i;:::-;658:14361;6193:10;;;6228:12;:::i;:::-;658:14361;6130:13;;5953:115;658:14361;;-1:-1:-1;;;6026:31:15;;658:14361;;6026:31;5958:45;;;;658:14361;5958:45;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;;;:::i;658:14361::-;;;;;;;:::i;:::-;3839:2:8;;;;;;:::i;:::-;3874:14;;:19;:170;;;;;658:14361:15;3853:233:8;;;:::i;3874:170::-;3913:66;658:14361:15;;;;;;;;;;3892:1:8;658:14361:15;;7310:45:8;;;;;;;;;3913:66;;;;3954:10;658:14361:15;3913:66:8;;658:14361:15;;;;;;;;;;;;;;;;;;;;;3913:66:8;;;;;;3853:233;3913:66;3892:1;3913:66;;;3874:170;-1:-1:-1;;;;;;;658:14361:15;3913:131:8;3874:170;;;;3913:66;;;;;;;;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;;;;;;;658:14361:15;;;;;;;;;;;;;;;;;:::i;:::-;;;;9592:8;658:14361;;;:::i;:::-;9592:8;;:::i;658:14361::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;;;:::i;:::-;6917:8;;;:::i;:::-;658:14361;;-1:-1:-1;;;6942:40:15;;658:14361;;;6942:40;;658:14361;6942:40;;;:::i;:::-;;658:14361;6942:18;-1:-1:-1;;;;;658:14361:15;6942:40;;;;;;;-1:-1:-1;6942:40:15;;;658:14361;6941:41;;6937:110;;7113:7;658:14361;;;;;;7073:10;;7113:7;:::i;6942:40::-;;;;658:14361;6942:40;;;;;;;;;:::i;:::-;;;;658:14361;;;;;;;:::i;:::-;5497:8;;;;:::i;:::-;658:14361;;-1:-1:-1;;;5522:45:15;;;658:14361;;5522:45;;658:14361;5522:45;;;:::i;:::-;;658:14361;5522:18;-1:-1:-1;;;;;658:14361:15;5522:45;;;;;;;-1:-1:-1;5522:45:15;;;658:14361;5521:46;;5517:115;;5691:8;5656:10;;5691:8;:::i;5522:45::-;;;;;;;;;;;;;;:::i;:::-;;;;658:14361;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;1572:19:8;;658:14361:15;;-1:-1:-1;658:14361:15;1626:10:8;658:14361:15;;;;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;956:42;658:14361;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;-1:-1:-1;658:14361:15;;;5269:14;658:14361;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;9800:34;;;;;;;9796:93;;9966:1;9969:20;;;;;;658:14361;9954:13;10034:10;10046:12;10034:10;658:14361;10034:10;;;;:::i;:::-;658:14361;;;;:::i;:::-;10046:12;;;;;:::i;:::-;658:14361;10046:12;;;:::i;:::-;658:14361;9954:13;;9796:93;658:14361;;-1:-1:-1;;;9857:21:15;;658:14361;;9857:21;658:14361;;;;;;;;;;;;;;;;;924:20:8;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;924:20:8;658:14361:15;;;-1:-1:-1;658:14361:15;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;2843:10:8;-1:-1:-1;658:14361:15;2826:16:8;658:14361:15;;2826:38:8;658:14361:15;;-1:-1:-1;658:14361:15;2826:38:8;:::i;:::-;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;2843:10:8;2891:46;658:14361:15;2843:10:8;2891:46;;658:14361:15;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;:::i;:::-;7395:8;;;;:::i;:::-;658:14361;;-1:-1:-1;;;7419:45:15;;658:14361;;;7419:45;;658:14361;7419:45;;;:::i;:::-;;658:14361;7419:18;-1:-1:-1;;;;;658:14361:15;7419:45;;;;;;;-1:-1:-1;7419:45:15;;;658:14361;7418:46;;7414:115;;-1:-1:-1;7606:15:15;;;;;;658:14361;7591:13;7755:12;7785:11;7755:12;658:14361;7755:12;;;;:::i;:::-;658:14361;7785:11;;;;;:::i;:::-;658:14361;7672:10;;;;7785:11;:::i;:::-;658:14361;7591:13;;7419:45;;;;658:14361;7419:45;;;;;;;;;:::i;:::-;;;;658:14361;;;;;;;:::i;:::-;8577:39;;;;;;;8573:98;;8753:1;8756:20;;;;;;658:14361;8741:13;8820:15;8837:12;8820:15;658:14361;8820:15;;;;:::i;:::-;658:14361;;;;:::i;:::-;8837:12;;;;;:::i;:::-;658:14361;8837:12;;;:::i;:::-;658:14361;8741:13;;658:14361;;;;;;;:::i;:::-;6524:8;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;;956:42;6548:13;;6544:69;;10985:38;658:14361;;;;;;;10985:38;;;;;;658:14361;10985:38;;;:::i;:::-;;:16;;658:14361;10985:38;;;;;;;-1:-1:-1;10985:38:15;;;658:14361;10984:39;;10980:106;;11146:4;11153:7;11228:41;11146:4;11228:41;11146:4;;6636:10;;11153:7;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;11172:12;658:14361;;;;;11172:30;;:20;658:14361;;;;;;;;;11172:20;658:14361;;;;;;;;;;11172:30;:41;658:14361;;;11172:41;:::i;:::-;658:14361;;;;11228:41;;;;;:::i;:::-;;;;658:14361;10980:106;658:14361;;-1:-1:-1;;;11046:29:15;;658:14361;;11046:29;10985:38;;;;;;;;;;;;;;:::i;:::-;;;;6544:69;658:14361;;-1:-1:-1;;;6584:18:15;;658:14361;;6584:18;658:14361;;;;;;;:::i;:::-;4270:2:8;;;;;;;;;:::i;:::-;4305:14;;:19;:172;;;;;658:14361:15;4284:235:8;;;:::i;4305:172::-;4344:68;658:14361:15;;;;4323:1:8;658:14361:15;;;;;;;;;;;;7310:45:8;;;;;;;;;;;4344:68;;;;4385:10;658:14361:15;4344:68:8;;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;4344:68:8;;;658:14361:15;4344:68:8;;;;;;4284:235;4344:68;4323:1;4344:68;;;4305:172;-1:-1:-1;;;;;;;658:14361:15;4344:133:8;4305:172;;;;;;4344:68;;;;;;;;;;;;;;:::i;:::-;;;;658:14361:15;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;:::i;:::-;;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;658:14361:15;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;9064:6;658:14361;;;;;:::i;:::-;;;9064:6;:::i;658:14361::-;;;;;;-1:-1:-1;;658:14361:15;;;;10243:8;658:14361;;10243:8;:::i;658:14361::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;;;;:::i;:::-;;;;;;;;;-1:-1:-1;;10429:26:15;-1:-1:-1;;;10429:26:15;24801:17:2;;;;24797:103;;658:14361:15;-1:-1:-1;;;;24926:8:2;-1:-1:-1;24917:17:2;;;;24913:103;;658:14361:15;25042:8:2;;25033:17;;;;25029:103;;658:14361:15;25158:7:2;;25149:16;;;;25145:100;;658:14361:15;25271:7:2;;25262:16;;;;25258:100;;658:14361:15;25375:16:2;25384:7;25375:16;;;25371:100;;658:14361:15;25497:7:2;25488:16;;;;25484:66;;658:14361:15;779:1:1;658:14361:15;;921:76:1;817:18;658:14361:15;;;817:18:1;:::i;:::-;849:11;921:76;;;1010:282;779:1;;;1010:282;658:14361:15;10404:52;;;;:::i;1010:282:1:-;-1:-1:-1;;658:14361:15;;;;-1:-1:-1;;;1115:95:1;;;;658:14361:15;1115:95:1;658:14361:15;1227:11:1;;1260:10;1256:21;;1010:282;;;;;1256:21;1272:5;;25484:66:2;658:14361:15;25534:1:2;658:14361:15;25484:66:2;;;25371:100;658:14361:15;;25384:7:2;25455:1;658:14361:15;;;;25371:100:2;;;25258;658:14361:15;;;;;;;25258:100:2;;;;25145;25229:1;658:14361:15;;;;;;25145:100:2;;;;25029:103;25115:2;658:14361:15;;;;;;25029:103:2;;;;24913;658:14361:15;;;;;;;24913:103:2;;;;24797;658:14361:15;;-1:-1:-1;658:14361:15;;-1:-1:-1;24797:103:2;;;;658:14361:15;-1:-1:-1;;;;;658:14361:15;;;;;5509:10:8;658:14361:15;;;;;;:::o;:::-;-1:-1:-1;;;;;658:14361:15;;;;;10706:13;658:14361;;;;;;:::o;:::-;-1:-1:-1;;;;;658:14361:15;;;;;11623:14;658:14361;;;;;;:::o;:::-;;;;;;;;;;;;;;;;:::o;:::-;;;;;;-1:-1:-1;;658:14361:15;;;;;;1897:68:8;658:14361:15;;;;;:::i;:::-;;;;;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;-1:-1:-1;658:14361:15;;;1897:68:8;658:14361:15;;;;;1897:68:8;:::i;:::-;658:14361:15;;;;;;;;;;;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;:::i;:::-;9231:13;;-1:-1:-1;9246:18:15;;;;;;658:14361;9231:13;9307:10;;;658:14361;9307:10;;;;:::i;:::-;658:14361;;;;:::i;:::-;9307:10;;:::i;:::-;658:14361;9231:13;;658:14361;;;;;;-1:-1:-1;;658:14361:15;;;;;;;;:::i;:::-;;;;;:::i;:::-;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;:::i;:::-;-1:-1:-1;;658:14361:15;;-1:-1:-1;;;658:14361:15;;;;;;;;;8365:8;658:14361;;;:::i;:::-;8365:8;;:::i;658:14361::-;;;;;;-1:-1:-1;;658:14361:15;;;;3509:15;658:14361;;;;;:::i;:::-;;;3509:15;:::i;658:14361::-;;;;:::o;:::-;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;1327:149:8;-1:-1:-1;658:14361:15;;;1427:8:8;658:14361:15;;;;;;-1:-1:-1;;;;;658:14361:15;;1410:59:8;1418:36;;;1410:59;:::i;:::-;1327:149::o;658:14361:15:-;;;;:::o;:::-;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;2950:741:8;;658:14361:15;;;;;3081:12:8;;;658:14361:15;;5374:8:8;658:14361:15;;;;;;;3081:12:8;658:14361:15;;;;;;3073:20:8;;;658:14361:15;;3526:16:8;3596:17;658:14361:15;;;3127:16:8;3119:46;3127:16;;;3119:46;:::i;:::-;3197:10;;:18;:56;;;;2950:741;3197:89;;;;2950:741;3176:150;;;:::i;:::-;3526:16;:::i;:::-;658:14361:15;;-1:-1:-1;;658:14361:15;;;3559:14:8;;;:::i;:::-;658:14361:15;;;;;;3596:12:8;;658:14361:15;;5374:8:8;658:14361:15;;;;;;;3596:17:8;658:14361:15;3631:15:8;;;:::i;:::-;658:14361:15;;-1:-1:-1;;;;;;658:14361:15;;;;;-1:-1:-1;;;;;;;;;;;;3662:22:8;;2950:741::o;3197:89::-;3271:15;3176:150;3257:29;3271:15;;;;:::i;:::-;658:14361:15;-1:-1:-1;;;;;658:14361:15;;;3271:15:8;-1:-1:-1;;;;;658:14361:15;;;3257:29:8;3197:10;3257:29;3197:89;;;;:56;:10;3219:34;;3197:10;3219:22;;658:14361:15;;;;;;;;3219:16:8;658:14361:15;;;;;;;3219:22:8;:34;:::i;:::-;658:14361:15;;;;;3219:34:8;3197:56;;658:14361:15;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::o;:::-;;;;;;;;;;;;;;:::o;:::-;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;-1:-1:-1;;;658:14361:15;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;:::i;3569:1183::-;;;;;;;;;;3869:10;;;;:::i;:::-;3950:36;;;3946:95;;4067:1;4070:20;;;;;;4294:13;;;;;4067:1;4309:15;;;;;;4522:13;;;4067:1;4537:22;;;;;;4736:8;;;;;;;;:::i;4522:13::-;4604:17;4623:20;4604:17;;658:14361;4604:17;;;;:::i;:::-;;:::i;:::-;4623:20;;;;;:::i;:::-;658:14361;4623:20;;;:::i;:::-;658:14361;4522:13;;4294;4367:10;;;;658:14361;4367:10;;;;:::i;:::-;;;:::i;:::-;658:14361;4294:13;;4055;4134:15;4151:12;4134:15;;;658:14361;4134:15;;;;:::i;:::-;4151:12;;;;;:::i;:::-;658:14361;4151:12;;:::i;:::-;658:14361;4055:13;;658:14361;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;;;:::o;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;-1:-1:-1;;658:14361:15;;;;:::o;838:32::-;;;;;;;658:14361;;;;838:32;658:14361;;;838:32;;;;;;;;;:::i;:::-;;;;658:14361;;838:32;;;;;;;;;:::i;:::-;;;;;;;;;:::i;658:14361::-;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;;;;;;:::o;:::-;-1:-1:-1;;;;;658:14361:15;;;;;;;;;;;;;;;;;;;;;:::o;10469:355::-;;-1:-1:-1;;;;;658:14361:15;;10626:69;;;;;658:14361;10626:69;658:14361;10626:69;658:14361;;;;;;;;;;;;;10626:69;;10679:4;10626:69;;;;;:::i;:::-;;;;;;;;;;10769:48;10626:69;10769:48;10626:69;;;10469:355;10706:26;;;;:::i;:::-;658:14361;10626:69;658:14361;;;;;10626:69;658:14361;;;;10769:48;;;;;:::i;:::-;;;;10469:355::o;10626:69::-;;;;:::i;:::-;;;;1328:1782:10;;-1:-1:-1;1328:1782:10;;1532:1521;1328:1782;1532:1521;1328:1782;1532:1521;;658:14361:15;;;;1532:1521:10;;658:14361:15;;;;;1532:1521:10;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;1532:1521:10;;;;;658:14361:15;;;1328:1782:10:o;658:14361:15:-;1532:1521:10;658:14361:15;-1:-1:-1;;;658:14361:15;;1532:1521:10;;658:14361:15;;;;1532:1521:10;658:14361:15;;;-1:-1:-1;;;1532:1521:10;658:14361:15;;;1532:1521:10;;658:14361:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;11282:469::-;;;;;-1:-1:-1;;;;;658:14361:15;;;11460:152;;;;;658:14361;;;;;;;;;;;;11460:152;;;;;11538:4;;;;;;11460:152;;;;;:::i;:::-;;;;;;;;;11691:53;11460:152;11691:53;11460:152;658:14361;11460:152;;;11282:469;11623:22;;;;:::i;:::-;658:14361;;;;;;;;;;;;;;11623:53;658:14361;;;11623:53;:::i;:::-;658:14361;;;;11691:53;;;;;:::i;11460:152::-;;;;:::i;:::-;;;;12069:483;12223:8;;;:::i;:::-;12247:26;:36;:26;;;;:::i;:36::-;658:14361;12247:48;12243:106;;-1:-1:-1;;;;;658:14361:15;;;12358:69;;;;;-1:-1:-1;658:14361:15;;;;;;;12358:69;;12406:10;;;12358:69;12406:10;;12399:4;12358:69;;;;:::i;:::-;;;;;;;;;;12497:48;12358:69;12497:48;12358:69;;;12069:483;12445:26;-1:-1:-1;12445:36:15;:26;;;;:::i;:36::-;658:14361;;;12497:48;;;;;:::i;12358:69::-;;;;;;:::i;:::-;;;:::i;:::-;;;;12243:106;658:14361;;-1:-1:-1;;;12318:20:15;;;;;12558:391;;;12658:8;;;:::i;:::-;-1:-1:-1;;;;;658:14361:15;;-1:-1:-1;658:14361:15;;;12695:12;658:14361;;;;;;;;;;;;;;;;;;;-1:-1:-1;658:14361:15;;-1:-1:-1;12739:11:15;;12735:48;;658:14361;3294:1377:10;658:14361:15;;;;;12695:12;658:14361;;;;;;;;;;;;;;;3294:1377:10;;;;;;;;;12867:10:15;3294:1377:10;;;;;;;;;;;;;;;;;;;;;;;658:14361:15;;;;12902:40;658:14361;12902:40;658:14361;;;12902:40;;;;;:::i;658:14361::-;;;;;;;;;;;3294:1377:10;658:14361:15;;;;3294:1377:10;658:14361:15;;;-1:-1:-1;;;3294:1377:10;658:14361:15;;;;12735:48;12766:7;;;;;;;;:::o;12955:582::-;13105:8;;;:::i;:::-;13142:42;:22;:32;:22;;;;:::i;:42::-;658:14361;13198:11;;;13194:48;;12358:69;13258:42;:22;:32;:22;;;;:::i;:42::-;658:14361;-1:-1:-1;;;;;658:14361:15;;;13311:151;;;;;12358:69;658:14361;;;;;;;13311:151;;13384:10;;;13311:151;13384:10;;;13365:4;13311:151;;;;:::i;:::-;;;;;;;;;;13478:52;13311:151;13478:52;13311:151;;;12955:582;658:14361;;;13478:52;;;;;:::i;13311:151::-;;;;;;:::i;:::-;;;;13194:48;13225:7;;;;:::o;13543:193::-;;;-1:-1:-1;;;;;658:14361:15;14617:17;13543:193;14617:17;:::i;:::-;658:14361;14603:10;:31;;:95;;;13543:193;14603:146;;;13543:193;14586:232;;-1:-1:-1;13682:47:15;-1:-1:-1;;13682:29:15;-1:-1:-1;;658:14361:15;;;;5690:8:8;658:14361:15;;;;;;;5713:42:8;5721:19;;;5713:42;:::i;:::-;658:14361:15;;;5845:10:8;658:14361:15;;;;;;;;;;;;5892:12:8;;658:14361:15;;5374:8:8;658:14361:15;;;;;;;5892:12:8;658:14361:15;;-1:-1:-1;;;;;;658:14361:15;;;;;;5922:15:8;;;:::i;:::-;658:14361:15;;;;;;-1:-1:-1;;;;;;;;;;;5953:31:8;;;658:14361:15;;13682:19;658:14361;;;;;;;14586:232;658:14361;;-1:-1:-1;;;14781:26:15;;;;;658:14361;;;;;14781:26;14603:146;:10;;14714:21;;;;:::i;:::-;658:14361;;14714:35;;14603:146;;:95;14668:17;;;;;:::i;:::-;658:14361;-1:-1:-1;658:14361:15;14651:16;658:14361;;;14651:47;14603:10;658:14361;-1:-1:-1;658:14361:15;14651:47;:::i;:::-;658:14361;;14650:48;14603:95;;13742:450;;13824:8;;;:::i;:::-;-1:-1:-1;658:14361:15;;;;;;;;;;;;;;;956:42;13902:11;;13898:48;;658:14361;;13861:12;658:14361;;;;;;;;;;;;;;;14024:10;;;;;;14016:43;;658:14361;;;;;;;;;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;;14073:5;14069:64;;658:14361;;;;;956:42;658:14361;;;;;;;;;14148:37;;658:14361;;;;14148:37;658:14361;14069:64;658:14361;;-1:-1:-1;;;14101:21:15;;;;;658:14361;;;;13898:48;13929:7;;;;;;:::o;14198:318::-;-1:-1:-1;658:14361:15;;;14338:8;658:14361;;;;;;-1:-1:-1;;;;;658:14361:15;14366:144;;;14198:318::o;14366:144::-;14284:28;;;-1:-1:-1;14366:144:15;;-1:-1:-1;14366:144:15;14830:187;-1:-1:-1;658:14361:15;;;14908:19;658:14361;;;;;;-1:-1:-1;;;;;658:14361:15;14941:10;14908:43;14904:107;;14830:187;:::o;14904:107::-;658:14361;;;;14781:26;;;;14974;;;;;658:14361;14974:26

Swarm Source

ipfs://2bf1d4303a974a9c365b5d1e50143197a6e985423861903be649efb0c9359bcd
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.